195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
29c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	<http://rt2x00.serialmonkey.com>
495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	This program is free software; you can redistribute it and/or modify
695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	it under the terms of the GNU General Public License as published by
795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	the Free Software Foundation; either version 2 of the License, or
895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	(at your option) any later version.
995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	This program is distributed in the hope that it will be useful,
1195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	but WITHOUT ANY WARRANTY; without even the implied warranty of
1295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	GNU General Public License for more details.
1495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	You should have received a copy of the GNU General Public License
1695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	along with this program; if not, write to the
1795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	Free Software Foundation, Inc.,
1895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
2095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
2195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
2295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	Module: rt2400pci
2395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	Abstract: rt2400pci device specific routines.
2495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	Supported chipsets: RT2460.
2595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
2695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
2795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/delay.h>
2895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/etherdevice.h>
2995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/init.h>
3095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/kernel.h>
3195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/module.h>
3295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/pci.h>
3395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/eeprom_93cx6.h>
345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
3595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include "rt2x00.h"
3795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include "rt2x00pci.h"
3895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include "rt2400pci.h"
3995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
4095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
4195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Register access.
4295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * All access to the CSR registers will go through the methods
4395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * rt2x00pci_register_read and rt2x00pci_register_write.
4495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * BBP and RF register require indirect register access,
4595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * and use the CSR registers BBPCSR and RFCSR to achieve this.
4695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * These indirect registers work with busy bits,
4795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * and we will try maximal REGISTER_BUSY_COUNT times to access
4895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * the register while taking a REGISTER_BUSY_DELAY us delay
49f5a9987dfbe219ffc361ebf126e1797db4abbcfeMark Einon * between each attempt. When the busy bit is still set at that time,
5095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * the access attempt is considered to have failed,
5195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * and we will print an error.
5295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
53c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn#define WAIT_FOR_BBP(__dev, __reg) \
54c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
55c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn#define WAIT_FOR_RF(__dev, __reg) \
56c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
5795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
580e14f6d3e088473b411d35ff63737e46efb9e6dfAdam Bakerstatic void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
5995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn				const unsigned int word, const u8 value)
6095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
6195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
6295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
638ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_lock(&rt2x00dev->csr_mutex);
648ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn
6595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
66c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * Wait until the BBP becomes available, afterwards we
67c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * can safely write the new data into the register.
6895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
69c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
70c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		reg = 0;
71c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
72c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
73c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
74c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
75c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn
76c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
77c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	}
788ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn
798ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_unlock(&rt2x00dev->csr_mutex);
8095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
8195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
820e14f6d3e088473b411d35ff63737e46efb9e6dfAdam Bakerstatic void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
8395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			       const unsigned int word, u8 *value)
8495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
8595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
8695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
878ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_lock(&rt2x00dev->csr_mutex);
888ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn
8995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
90c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * Wait until the BBP becomes available, afterwards we
91c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * can safely write the read request into the register.
92c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * After the data has been written, we wait until hardware
93c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * returns the correct value, if at any time the register
94c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * doesn't become available in time, reg will be 0xffffffff
95c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * which means we return 0xff to the caller.
9695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
97c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
98c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		reg = 0;
99c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
100c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
101c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
10295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
103c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
10495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
105c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		WAIT_FOR_BBP(rt2x00dev, &reg);
106c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	}
10795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
10895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
1098ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn
1108ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_unlock(&rt2x00dev->csr_mutex);
11195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
11295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1130e14f6d3e088473b411d35ff63737e46efb9e6dfAdam Bakerstatic void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
11495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			       const unsigned int word, const u32 value)
11595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
11695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
11795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1188ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_lock(&rt2x00dev->csr_mutex);
1198ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn
120c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	/*
121c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * Wait until the RF becomes available, afterwards we
122c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 * can safely write the new data into the register.
123c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	 */
124c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn	if (WAIT_FOR_RF(rt2x00dev, &reg)) {
125c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		reg = 0;
126c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, RFCSR_VALUE, value);
127c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
128c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
129c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
130c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn
131c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
132c9c3b1a5deac4297503145840fffcd122b253db5Ivo van Doorn		rt2x00_rf_write(rt2x00dev, word, value);
13395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
13495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1358ff48a8bbe4a1ba29dea2836dfce74660f97c1beIvo van Doorn	mutex_unlock(&rt2x00dev->csr_mutex);
13695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
13795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
13895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
13995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
14095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct rt2x00_dev *rt2x00dev = eeprom->data;
14195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
14295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
14395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
14495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
14595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
14695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
14795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom->reg_data_clock =
14895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	    !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
14995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom->reg_chip_select =
15095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	    !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
15195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
15295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
15395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
15495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
15595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct rt2x00_dev *rt2x00dev = eeprom->data;
15695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg = 0;
15795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
15895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
15995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
16095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_CLOCK,
16195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			   !!eeprom->reg_data_clock);
16295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
16395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			   !!eeprom->reg_chip_select);
16495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
16595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR21, reg);
16695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
16795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
16895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#ifdef CONFIG_RT2X00_LIB_DEBUGFS
16995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic const struct rt2x00debug rt2400pci_rt2x00debug = {
17095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.owner	= THIS_MODULE,
17195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.csr	= {
172743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.read		= rt2x00pci_register_read,
173743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.write		= rt2x00pci_register_write,
174743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.flags		= RT2X00DEBUGFS_OFFSET,
175743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.word_base	= CSR_REG_BASE,
17695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_size	= sizeof(u32),
17795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_count	= CSR_REG_SIZE / sizeof(u32),
17895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	},
17995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.eeprom	= {
18095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.read		= rt2x00_eeprom_read,
18195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.write		= rt2x00_eeprom_write,
182743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.word_base	= EEPROM_BASE,
18395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_size	= sizeof(u16),
18495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_count	= EEPROM_SIZE / sizeof(u16),
18595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	},
18695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.bbp	= {
18795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.read		= rt2400pci_bbp_read,
18895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.write		= rt2400pci_bbp_write,
189743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.word_base	= BBP_BASE,
19095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_size	= sizeof(u8),
19195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_count	= BBP_SIZE / sizeof(u8),
19295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	},
19395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.rf	= {
19495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.read		= rt2x00_rf_read,
19595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.write		= rt2400pci_rf_write,
196743b97caf98036ec8ee4bfc6fc6f85ad94e04783Ivo van Doorn		.word_base	= RF_BASE,
19795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_size	= sizeof(u32),
19895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		.word_count	= RF_SIZE / sizeof(u32),
19995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	},
20095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
20195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
20295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
20395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
20495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
20595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
20695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
20795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
20895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return rt2x00_get_field32(reg, GPIOCSR_BIT0);
20995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
21095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
211771fd565195727d12f0b75d918b9fcb9f33a5476Ivo van Doorn#ifdef CONFIG_RT2X00_LIB_LEDS
212a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doornstatic void rt2400pci_brightness_set(struct led_classdev *led_cdev,
213a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn				     enum led_brightness brightness)
214a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn{
215a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	struct rt2x00_led *led =
216a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	    container_of(led_cdev, struct rt2x00_led, led_dev);
217a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	unsigned int enabled = brightness != LED_OFF;
218a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	u32 reg;
219a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn
220a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
221a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn
222a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
223a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn		rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
224a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	else if (led->type == LED_TYPE_ACTIVITY)
225a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
226a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn
227a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
228a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn}
229a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn
230a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doornstatic int rt2400pci_blink_set(struct led_classdev *led_cdev,
231a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn			       unsigned long *delay_on,
232a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn			       unsigned long *delay_off)
233a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn{
234a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	struct rt2x00_led *led =
235a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	    container_of(led_cdev, struct rt2x00_led, led_dev);
236a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	u32 reg;
237a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn
238a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
239a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
240a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
241a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
242a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn
243a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn	return 0;
244a2e1d52a32eab53f8ab03c4023310f65aaa054a7Ivo van Doorn}
245475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn
246475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doornstatic void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
247475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn			       struct rt2x00_led *led,
248475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn			       enum led_type type)
249475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn{
250475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	led->rt2x00dev = rt2x00dev;
251475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	led->type = type;
252475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	led->led_dev.brightness_set = rt2400pci_brightness_set;
253475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	led->led_dev.blink_set = rt2400pci_blink_set;
254475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	led->flags = LED_INITIALIZED;
255475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn}
256771fd565195727d12f0b75d918b9fcb9f33a5476Ivo van Doorn#endif /* CONFIG_RT2X00_LIB_LEDS */
257a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn
25895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
25995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Configuration handlers.
26095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
2613a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doornstatic void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
2623a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn				    const unsigned int filter_flags)
2633a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn{
2643a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	u32 reg;
2653a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn
2663a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	/*
2673a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	 * Start configuration steps.
2683a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	 * Note that the version error will always be dropped
2693a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	 * since there is no filter for it at this time.
2703a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	 */
2713a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
2723a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
2733a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn			   !(filter_flags & FIF_FCSFAIL));
2743a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
2753a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn			   !(filter_flags & FIF_PLCPFAIL));
2763a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
2773a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn			   !(filter_flags & FIF_CONTROL));
2783a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
2793a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn			   !(filter_flags & FIF_PROMISC_IN_BSS));
2803a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
281e0b005fa1479045fe879944036268af3ebcd1835Ivo van Doorn			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
282e0b005fa1479045fe879944036268af3ebcd1835Ivo van Doorn			   !rt2x00dev->intf_ap_count);
2833a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
2843a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
2853a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn}
2863a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn
2876bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doornstatic void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
2886bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn				  struct rt2x00_intf *intf,
2896bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn				  struct rt2x00intf_conf *conf,
2906bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn				  const unsigned int flags)
29195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
2926bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	unsigned int bcn_preload;
2936bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	u32 reg;
29495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
2956bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	if (flags & CONFIG_UPDATE_TYPE) {
2966bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		/*
2976bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		 * Enable beacon config
2986bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		 */
299bad13639a30e1557fbe9d440adc1906673c9de4eIvo van Doorn		bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
3006bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
3016bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
3026bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
30395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3046bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		/*
3056bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		 * Enable synchronisation.
3066bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		 */
3076bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
3086bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
3096bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
3106bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	}
31195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3126bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	if (flags & CONFIG_UPDATE_MAC)
3136bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
3146bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn					      conf->mac, sizeof(conf->mac));
31595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3166bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	if (flags & CONFIG_UPDATE_BSSID)
3176bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn		rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
3186bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn					      conf->bssid, sizeof(conf->bssid));
31995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
32095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3213a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doornstatic void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
3220204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				 struct rt2x00lib_erp *erp,
3230204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				 u32 changed)
32495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
3255c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	int preamble_mask;
32695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
32795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
3285c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	/*
3295c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	 * When short preamble is enabled, we should set bit 0x08
3305c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	 */
3310204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
3320204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		preamble_mask = erp->short_preamble << 3;
3330204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3340204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
3350204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
3360204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
3370204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
3380204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
3390204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
3400204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3410204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
3420204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
3430204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
3440204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
3450204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   GET_DURATION(ACK_SIZE, 10));
3460204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
3470204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3480204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
3490204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
3500204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
3510204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
3520204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   GET_DURATION(ACK_SIZE, 20));
3530204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
3540204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3550204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
3560204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
3570204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
3580204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
3590204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   GET_DURATION(ACK_SIZE, 55));
3600204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
3610204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3620204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
3630204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
3640204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
3650204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, ARCSR2_LENGTH,
3660204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   GET_DURATION(ACK_SIZE, 110));
3670204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
3680204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	}
3690204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3700204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	if (changed & BSS_CHANGED_BASIC_RATES)
3710204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
3720204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3730204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	if (changed & BSS_CHANGED_ERP_SLOT) {
3740204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
3750204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
3760204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, CSR11, reg);
3770204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3780204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
3790204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
3800204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
3810204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, CSR18, reg);
3820204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3830204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
3840204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
3850204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
3860204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, CSR19, reg);
3870204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	}
3880204464329c17ba6d293e1899f71223599a0e582Helmut Schaa
3890204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	if (changed & BSS_CHANGED_BEACON_INT) {
3900204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
3910204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
3920204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   erp->beacon_int * 16);
3930204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
3940204464329c17ba6d293e1899f71223599a0e582Helmut Schaa				   erp->beacon_int * 16);
3950204464329c17ba6d293e1899f71223599a0e582Helmut Schaa		rt2x00pci_register_write(rt2x00dev, CSR12, reg);
3960204464329c17ba6d293e1899f71223599a0e582Helmut Schaa	}
39795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
39895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
399e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doornstatic void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
400e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn				 struct antenna_setup *ant)
40195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
402e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	u8 r1;
403e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	u8 r4;
404e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn
405e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	/*
406e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 * We should never come here because rt2x00lib is supposed
407e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 * to catch this and send us the correct antenna explicitely.
408e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 */
409e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
410e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	       ant->tx == ANTENNA_SW_DIVERSITY);
411e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn
412e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2400pci_bbp_read(rt2x00dev, 4, &r4);
413e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2400pci_bbp_read(rt2x00dev, 1, &r1);
414e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn
415e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	/*
416e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 * Configure the TX antenna.
417e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 */
418e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	switch (ant->tx) {
419e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_HW_DIVERSITY:
420e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
421e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
422e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_A:
423e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
424e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
425e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_B:
426e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	default:
427e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
428e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
429e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	}
430e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn
431e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	/*
432e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 * Configure the RX antenna.
433e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	 */
434e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	switch (ant->rx) {
435e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_HW_DIVERSITY:
436e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
437e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
438e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_A:
439e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
440e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
441e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	case ANTENNA_B:
442e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	default:
443e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
444e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		break;
445e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	}
446e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn
447e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2400pci_bbp_write(rt2x00dev, 4, r4);
448e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2400pci_bbp_write(rt2x00dev, 1, r1);
44995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
45095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
45195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
4525c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn				     struct rf_channel *rf)
45395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
45495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
45595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Switch on tuning bits.
45695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
4575c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
4585c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
45995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
4605c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
4615c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
4625c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
46395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
46495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
46595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * RF2420 chipset don't need any additional actions.
46695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
4675122d8986232ef2a761f5cf70c31666c4d65c3e4Gertjan van Wingerde	if (rt2x00_rf(rt2x00dev, RF2420))
46895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return;
46995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
47095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
47195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * For the RT2421 chipsets we need to write an invalid
47295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * reference clock rate to activate auto_tune.
47395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * After that we set the value back to the correct channel.
47495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
4755c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
47695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32);
4775c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
47895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
47995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	msleep(1);
48095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
4815c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
4825c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
4835c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
48495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
48595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	msleep(1);
48695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
48795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
48895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Switch off tuning bits.
48995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
4905c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
4915c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
49295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
4935c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
4945c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
49595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
49695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
49795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Clear false CRC during channel switch.
49895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
4995c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn	rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
50095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
50195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
50295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
50395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
50495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
50595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
50695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
507e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doornstatic void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
508e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn					 struct rt2x00lib_conf *libconf)
50995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
510e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	u32 reg;
51195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
512e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
513e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
514e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn			   libconf->conf->long_frame_max_tx_count);
515e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
516e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn			   libconf->conf->short_frame_max_tx_count);
517e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
51895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
51995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
5207d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doornstatic void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
5217d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn				struct rt2x00lib_conf *libconf)
5227d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn{
5237d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	enum dev_state state =
5247d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	    (libconf->conf->flags & IEEE80211_CONF_PS) ?
5257d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		STATE_SLEEP : STATE_AWAKE;
5267d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	u32 reg;
5277d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn
5287d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	if (state == STATE_SLEEP) {
5297d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
5307d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
5316b347bff145f9a8a0972ca8fc3c44dd1f91b0f16Ivo van Doorn				   (rt2x00dev->beacon_int - 20) * 16);
5327d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
5337d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn				   libconf->conf->listen_interval - 1);
5347d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn
5357d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		/* We must first disable autowake before it can be enabled */
5367d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
5377d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR20, reg);
5387d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn
5397d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
5407d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR20, reg);
5415731858d0047cad309d334c4cd6ccb6199bf28feGertjan van Wingerde	} else {
5425731858d0047cad309d334c4cd6ccb6199bf28feGertjan van Wingerde		rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
5435731858d0047cad309d334c4cd6ccb6199bf28feGertjan van Wingerde		rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
5445731858d0047cad309d334c4cd6ccb6199bf28feGertjan van Wingerde		rt2x00pci_register_write(rt2x00dev, CSR20, reg);
5457d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	}
5467d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn
5477d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
5487d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn}
5497d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn
55095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
5516bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn			     struct rt2x00lib_conf *libconf,
5526bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn			     const unsigned int flags)
55395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
554e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
5555c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn		rt2400pci_config_channel(rt2x00dev, &libconf->rf);
556e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	if (flags & IEEE80211_CONF_CHANGE_POWER)
5575c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn		rt2400pci_config_txpower(rt2x00dev,
5585c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn					 libconf->conf->power_level);
559e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
560e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn		rt2400pci_config_retry_limit(rt2x00dev, libconf);
5617d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn	if (flags & IEEE80211_CONF_CHANGE_PS)
5627d7f19ccb777946df0a8fb7c83189ba2ae08b02eIvo van Doorn		rt2400pci_config_ps(rt2x00dev, libconf);
56395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
56495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
56595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
566181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn				const int cw_min, const int cw_max)
56795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
56895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
56995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
57095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
571181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
572181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
57395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
57495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
57595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
57695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
57795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Link tuning
57895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
579ebcf26dae9f10e247ea41ef66f89b336ba456097Ivo van Doornstatic void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
580ebcf26dae9f10e247ea41ef66f89b336ba456097Ivo van Doorn				 struct link_qual *qual)
58195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
58295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
58395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u8 bbp;
58495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
58595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
58695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Update FCS error count from register.
58795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
58895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
589ebcf26dae9f10e247ea41ef66f89b336ba456097Ivo van Doorn	qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
59095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
59195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
59295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Update False CCA count from register.
59395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
59495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
595ebcf26dae9f10e247ea41ef66f89b336ba456097Ivo van Doorn	qual->false_cca = bbp;
59695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
59795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
5985352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doornstatic inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
5995352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn				     struct link_qual *qual, u8 vgc_level)
600eb20b4e8a6998ca68d9ac0963ee36a1a36fe241dIvo van Doorn{
601223dcc26591aa8e4a6bf623164b775b5bd89c9e1Ivo van Doorn	if (qual->vgc_level_reg != vgc_level) {
602223dcc26591aa8e4a6bf623164b775b5bd89c9e1Ivo van Doorn		rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
603223dcc26591aa8e4a6bf623164b775b5bd89c9e1Ivo van Doorn		qual->vgc_level = vgc_level;
604223dcc26591aa8e4a6bf623164b775b5bd89c9e1Ivo van Doorn		qual->vgc_level_reg = vgc_level;
605223dcc26591aa8e4a6bf623164b775b5bd89c9e1Ivo van Doorn	}
606eb20b4e8a6998ca68d9ac0963ee36a1a36fe241dIvo van Doorn}
607eb20b4e8a6998ca68d9ac0963ee36a1a36fe241dIvo van Doorn
6085352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doornstatic void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
6095352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn				  struct link_qual *qual)
61095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
6115352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn	rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
61295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
61395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
6145352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doornstatic void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
6155352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn				 struct link_qual *qual, const u32 count)
61695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
61795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
61895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * The link tuner should not run longer then 60 seconds,
61995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * and should run once every 2 seconds.
62095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
6215352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn	if (count > 60 || !(count & 1))
62295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return;
62395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
62495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
62595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Base r13 link tuning on the false cca count.
62695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
6275352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn	if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
6285352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn		rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
6295352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn	else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
6305352ff6510422d9a9bf13b7272f865eb53247f4dIvo van Doorn		rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
63195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
63295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
63395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
6345450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn * Queue handlers.
6355450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn */
6365450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2400pci_start_queue(struct data_queue *queue)
6375450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
6385450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
6395450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	u32 reg;
6405450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
6415450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
6425450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_RX:
6435450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
6445450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
6455450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
6465450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6475450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_BEACON:
6485450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
6495450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
6505450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
6515450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
6525450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
6535450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6545450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
6555450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6565450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	}
6575450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
6585450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
6595450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2400pci_kick_queue(struct data_queue *queue)
6605450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
6615450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
6625450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	u32 reg;
6635450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
6645450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
665f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VO:
6665450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
6675450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
6685450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
6695450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
670f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VI:
6715450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
6725450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
6735450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
6745450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6755450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_ATIM:
6765450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
6775450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
6785450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
6795450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6805450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
6815450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6825450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	}
6835450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
6845450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
6855450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2400pci_stop_queue(struct data_queue *queue)
6865450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
6875450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
6885450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	u32 reg;
6895450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
6905450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
691f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VO:
692f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VI:
6935450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_ATIM:
6945450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
6955450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
6965450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
6975450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
6985450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_RX:
6995450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
7005450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
7015450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
7025450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
7035450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_BEACON:
7045450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
7055450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
7065450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
7075450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
7085450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
709bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
710bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		/*
711bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 * Wait for possibly running tbtt tasklets.
712bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 */
713abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->tbtt_tasklet);
7145450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
7155450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
7165450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
7175450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	}
7185450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
7195450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
7205450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn/*
72195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Initialization functions.
72295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
723798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doornstatic bool rt2400pci_get_entry_state(struct queue_entry *entry)
72495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
725b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
72695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word;
72795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
728798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	if (entry->queue->qid == QID_RX) {
729798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
73095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
731798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
732798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	} else {
733798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
73495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
735798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
736798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		        rt2x00_get_field32(word, TXD_W0_VALID));
737798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	}
73895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
73995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
740798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doornstatic void rt2400pci_clear_entry(struct queue_entry *entry)
74195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
742b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
743798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
74495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word;
74595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
746798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	if (entry->queue->qid == QID_RX) {
747798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 2, &word);
748798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
749798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_write(entry_priv->desc, 2, word);
750798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn
751798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 1, &word);
752798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
753798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_write(entry_priv->desc, 1, word);
754798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn
755798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
756798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
757798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_write(entry_priv->desc, 0, word);
758798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	} else {
759798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
760798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_set_field32(&word, TXD_W0_VALID, 0);
761798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
762798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn		rt2x00_desc_write(entry_priv->desc, 0, word);
763798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	}
76495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
76595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
766181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
76795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
768b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	struct queue_entry_priv_pci *entry_priv;
76995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
77095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
77195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
77295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Initialize registers.
77395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
77495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
775181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
776181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
777e74df4a7562da56a7e4dbf41ff167b2f44e84a50Gertjan van Wingerde	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
778181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
77995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
78095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
781b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
78295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
78330b3a23c2594e122e7086f97b5252a87eaf8a817Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
784b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn			   entry_priv->desc_dma);
78595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
78695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
787b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
78895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
78930b3a23c2594e122e7086f97b5252a87eaf8a817Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
790b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn			   entry_priv->desc_dma);
79195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
79295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
793e74df4a7562da56a7e4dbf41ff167b2f44e84a50Gertjan van Wingerde	entry_priv = rt2x00dev->atim->entries[0].priv_data;
79495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
79530b3a23c2594e122e7086f97b5252a87eaf8a817Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
796b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn			   entry_priv->desc_dma);
79795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
79895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
799e74df4a7562da56a7e4dbf41ff167b2f44e84a50Gertjan van Wingerde	entry_priv = rt2x00dev->bcn->entries[0].priv_data;
80095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
80130b3a23c2594e122e7086f97b5252a87eaf8a817Ivo van Doorn	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
802b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn			   entry_priv->desc_dma);
80395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
80495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
80595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
80695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
807181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
80895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
80995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
810b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	entry_priv = rt2x00dev->rx->entries[0].priv_data;
81195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
812b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
813b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn			   entry_priv->desc_dma);
81495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
81595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
81695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
81795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
81895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
81995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
82095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
82195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
82295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
82395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
82495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
82595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20);
82695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
82795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
82895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, TIMECSR, &reg);
82995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
83095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
83195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
83295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
83395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
83495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR9, &reg);
83595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
83695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			   (rt2x00dev->rx->data_size / 128));
83795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR9, reg);
83895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
8391f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
8401f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
8411f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
8421f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
8431f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TCFP, 0);
8441f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
8451f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
8461f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
8471f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
8481f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
8491f90916264049a7d9e6106fd60d289c9a775d24fIvo van Doorn
85095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
85195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
85295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
85395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
85495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
85595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
85695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
85795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, ARCSR0, reg);
85895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
85995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, RXCSR3, &reg);
86095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
86195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
86295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
86395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
86495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 36); /* Rssi */
86595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
86695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
86795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
86895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
86995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
87095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
87195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -EBUSY;
87295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
87395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223);
87495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
87595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
87695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, MACCSR2, &reg);
87795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
87895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
87995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
88095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, RALINKCSR, &reg);
88195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
88295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
88395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
88495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
88595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
88695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
88795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
88895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
88995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
89095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
89195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR1, reg);
89295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
89395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
89495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
89595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
89695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR1, reg);
89795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
89895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
89995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * We must clear the FCS and FIFO error count.
90095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * These registers are cleared on read,
90195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * so we may pass a useless variable to store the value.
90295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
90395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
90495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CNT4, &reg);
90595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
90695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
90795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
90895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
9092b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doornstatic int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
91095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
91195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	unsigned int i;
91295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u8 value;
91395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
91495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
91595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		rt2400pci_bbp_read(rt2x00dev, 0, &value);
91695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		if ((value != 0xff) && (value != 0x00))
9172b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn			return 0;
91895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		udelay(REGISTER_BUSY_DELAY);
91995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
92095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
92195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
92295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return -EACCES;
9232b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn}
9242b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn
9252b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doornstatic int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
9262b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn{
9272b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	unsigned int i;
9282b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	u16 eeprom;
9292b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	u8 reg_id;
9302b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	u8 value;
9312b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn
9322b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev)))
9332b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		return -EACCES;
93495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
93595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 1, 0x00);
93695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 3, 0x27);
93795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 4, 0x08);
93895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 10, 0x0f);
93995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 15, 0x72);
94095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 16, 0x74);
94195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 17, 0x20);
94295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 18, 0x72);
94395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 19, 0x0b);
94495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 20, 0x00);
94595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 28, 0x11);
94695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 29, 0x04);
94795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
94895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
94995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
95095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
95195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
95295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
95395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		if (eeprom != 0xffff && eeprom != 0x0000) {
95495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
95595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
95695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			rt2400pci_bbp_write(rt2x00dev, reg_id, value);
95795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		}
95895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
95995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
96095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
96195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
96295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
96395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
96495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Device state switch handlers.
96595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
96695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
96795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn				 enum dev_state state)
96895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
969b550911abc0db069bb157f9769ffb7cf22c6c868Helmut Schaa	int mask = (state == STATE_RADIO_IRQ_OFF);
97095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
971bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	unsigned long flags;
97295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
97395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
97495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * When interrupts are being enabled, the interrupt registers
97595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * should clear the register to assure a clean state.
97695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
97795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (state == STATE_RADIO_IRQ_ON) {
97895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
97995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		rt2x00pci_register_write(rt2x00dev, CSR7, reg);
98095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
98195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
98295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
98395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Only toggle the interrupts bits we are going to use.
98495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Non-checked interrupt bits are disabled by default.
98595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
986bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
987bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
98895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
98995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
99095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
99195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
99295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
99395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
99495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
995bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
996bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
997bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
998bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	if (state == STATE_RADIO_IRQ_OFF) {
999bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		/*
1000bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 * Ensure that all tasklets are finished before
1001bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 * disabling the interrupts.
1002bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 */
1003abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->txstatus_tasklet);
1004abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->rxdone_tasklet);
1005abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->tbtt_tasklet);
1006bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	}
100795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
100895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
100995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
101095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
101195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
101295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Initialize all registers.
101395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
10142b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	if (unlikely(rt2400pci_init_queues(rt2x00dev) ||
10152b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		     rt2400pci_init_registers(rt2x00dev) ||
10162b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		     rt2400pci_init_bbp(rt2x00dev)))
101795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -EIO;
101895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
101995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
102095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
102195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
102295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
102395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
102495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1025a2c9b652a12a550d3d8509e9bae43bac396c5076Ivo van Doorn	 * Disable power
102695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1027a2c9b652a12a550d3d8509e9bae43bac396c5076Ivo van Doorn	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
102895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
102995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
103095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
103195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			       enum dev_state state)
103295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
10339655a6ec19ca656af246fb80817aa337892aefbfGertjan van Wingerde	u32 reg, reg2;
103495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	unsigned int i;
103595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	char put_to_sleep;
103695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	char bbp_state;
103795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	char rf_state;
103895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
103995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	put_to_sleep = (state != STATE_AWAKE);
104095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
104195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);
104295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
104395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
104495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
104595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
104695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
104795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
104895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
104995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Device is not guaranteed to be in the requested state yet.
105095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * We must wait until the register indicates that the
105195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * device has entered the correct state.
105295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
105395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
10549655a6ec19ca656af246fb80817aa337892aefbfGertjan van Wingerde		rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg2);
10559655a6ec19ca656af246fb80817aa337892aefbfGertjan van Wingerde		bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
10569655a6ec19ca656af246fb80817aa337892aefbfGertjan van Wingerde		rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
105795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		if (bbp_state == state && rf_state == state)
105895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			return 0;
10599655a6ec19ca656af246fb80817aa337892aefbfGertjan van Wingerde		rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
106095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		msleep(10);
106195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
106295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
106395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return -EBUSY;
106495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
106595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
106695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
106795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn				      enum dev_state state)
106895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
106995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	int retval = 0;
107095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
107195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	switch (state) {
107295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_RADIO_ON:
107395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		retval = rt2400pci_enable_radio(rt2x00dev);
107495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		break;
107595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_RADIO_OFF:
107695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		rt2400pci_disable_radio(rt2x00dev);
107795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		break;
10782b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	case STATE_RADIO_IRQ_ON:
10792b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	case STATE_RADIO_IRQ_OFF:
10802b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		rt2400pci_toggle_irq(rt2x00dev, state);
108195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		break;
108295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_DEEP_SLEEP:
108395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_SLEEP:
108495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_STANDBY:
108595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	case STATE_AWAKE:
108695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		retval = rt2400pci_set_state(rt2x00dev, state);
108795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		break;
108895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	default:
108995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		retval = -ENOTSUPP;
109095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		break;
109195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
109295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
10932b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn	if (unlikely(retval))
10942b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
10952b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn		      state, retval);
10962b08da3fb595432f87b5206c1c77dcb72300cacfIvo van Doorn
109795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return retval;
109895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
109995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
110095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
110195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * TX descriptor initialization
110295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
1103933314582ee5db00123683cf4c4d713ec9add306Ivo van Doornstatic void rt2400pci_write_tx_desc(struct queue_entry *entry,
110461486e0f68d1f8966c09b734566a187d42d65c54Ivo van Doorn				    struct txentry_desc *txdesc)
110595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
1106933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
1107933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
110885b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	__le32 *txd = entry_priv->desc;
110995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word;
111095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
111195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
111295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Start writing the descriptor words.
111395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
111485b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	rt2x00_desc_read(txd, 1, &word);
1115c4da004857056e6ee034c4110ccdcba659077b7eGertjan van Wingerde	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
111685b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	rt2x00_desc_write(txd, 1, word);
11174de36fe5abe077a4c65bf0b6a309865aa043e055Gertjan van Wingerde
111895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_read(txd, 2, &word);
1119df624ca5413d84b3082246de384823fbe8fed6e4Gertjan van Wingerde	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
1120df624ca5413d84b3082246de384823fbe8fed6e4Gertjan van Wingerde	rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
112195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_write(txd, 2, word);
112295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
112395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_read(txd, 3, &word);
112426a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
112549da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
112649da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
112726a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
112849da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
112949da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
113095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_write(txd, 3, word);
113195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
113295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_read(txd, 4, &word);
113326a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
113426a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa			   txdesc->u.plcp.length_low);
113549da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
113649da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
113726a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
113826a1d07f4176099a7b6f45009dad054e6ad5b7e4Helmut Schaa			   txdesc->u.plcp.length_high);
113949da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
114049da2605e27935835861a118df0671b5f004bfacIvo van Doorn	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
114195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_write(txd, 4, word);
114295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1143e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973Gertjan van Wingerde	/*
1144e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973Gertjan van Wingerde	 * Writing TXD word 0 must the last to prevent a race condition with
1145e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973Gertjan van Wingerde	 * the device, whereby the device may take hold of the TXD before we
1146e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973Gertjan van Wingerde	 * finished updating it.
1147e01f1ec35ff91c8a3f4a3e48a0c8ab476124b973Gertjan van Wingerde	 */
114895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_read(txd, 0, &word);
114995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
115095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
115195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
1152181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
115395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_ACK,
1154181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
115595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
1156181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
115795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_RTS,
1158181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
11592517794b702cf62bb049e57c0825fc4573f8a6a3Helmut Schaa	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
116095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
1161aade5102c5390280e7ae8a43e09b8995792f66d8Ivo van Doorn			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
116295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_desc_write(txd, 0, word);
116385b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde
116485b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	/*
116585b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	 * Register descriptor details in skb frame descriptor.
116685b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	 */
116785b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	skbdesc->desc = txd;
116885b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	skbdesc->desc_len = TXD_DESC_SIZE;
116995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
117095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
117195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
117295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * TX data initialization
117395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
1174f224f4ef794c4a9146a7fa7303018fecab8c9328Gertjan van Wingerdestatic void rt2400pci_write_beacon(struct queue_entry *entry,
1175f224f4ef794c4a9146a7fa7303018fecab8c9328Gertjan van Wingerde				   struct txentry_desc *txdesc)
1176bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn{
1177bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
1178bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	u32 reg;
1179bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn
1180bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	/*
1181bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	 * Disable beaconing while we are reloading the beacon data,
1182bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	 * otherwise we might be sending out invalid data.
1183bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	 */
1184bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
1185bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
1186bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
1187bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn
1188fa69560f317d961c56e29dea788b346d2b34fb87Ivo van Doorn	rt2x00queue_map_txskb(entry);
1189bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn
11905c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	/*
11915c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	 * Write the TX descriptor for the beacon.
11925c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	 */
1193933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	rt2400pci_write_tx_desc(entry, txdesc);
11945c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde
11955c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	/*
11965c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	 * Dump beacon to userspace through debugfs.
11975c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	 */
11985c3b685c79f38ac6b909b3650f3dad3993614cfbGertjan van Wingerde	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
1199d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde
1200d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde	/*
1201d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde	 * Enable beaconing again.
1202d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde	 */
1203d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
1204d61cb26696e19494c049297def6c8f37d9e2f534Gertjan van Wingerde	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
1205bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn}
1206bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn
120795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
120895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * RX control handlers
120995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
1210181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic void rt2400pci_fill_rxdone(struct queue_entry *entry,
1211181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn				  struct rxdone_entry_desc *rxdesc)
121295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
1213ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
1214b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
121595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word0;
121695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word2;
121789993890aeb8fe58b2d49b2661965524802ab73cIvo van Doorn	u32 word3;
1218ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	u32 word4;
1219ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	u64 tsf;
1220ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	u32 rx_low;
1221ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	u32 rx_high;
122295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1223b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	rt2x00_desc_read(entry_priv->desc, 0, &word0);
1224b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	rt2x00_desc_read(entry_priv->desc, 2, &word2);
1225b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	rt2x00_desc_read(entry_priv->desc, 3, &word3);
1226ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	rt2x00_desc_read(entry_priv->desc, 4, &word4);
122795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
12284150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
1229181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
12304150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
1231181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
123295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
123395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1234ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * We only get the lower 32bits from the timestamp,
1235ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * to get the full 64bits we must complement it with
1236ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * the timestamp from get_tsf().
1237ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * Note that when a wraparound of the lower 32bits
1238ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * has occurred between the frame arrival and the get_tsf()
1239ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * call, we must decrease the higher 32bits with 1 to get
1240ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 * to correct value.
1241ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	 */
124237a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller	tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
1243ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
1244ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	rx_high = upper_32_bits(tsf);
1245ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn
1246ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	if ((u32)tsf <= rx_low)
1247ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn		rx_high--;
1248ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn
1249ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	/*
125095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Obtain the status about this packet.
12518ed09854073ae0a19556d4d93cf79cf368c23673Ivo van Doorn	 * The signal is the PLCP value, and needs to be stripped
12528ed09854073ae0a19556d4d93cf79cf368c23673Ivo van Doorn	 * of the preamble bit (0x08).
125395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1254ae73e58ea64f121b26437a10937330e77ff48f33Ivo van Doorn	rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;
12558ed09854073ae0a19556d4d93cf79cf368c23673Ivo van Doorn	rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
125689993890aeb8fe58b2d49b2661965524802ab73cIvo van Doorn	rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
1257181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	    entry->queue->rt2x00dev->rssi_offset;
1258181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
125919d30e02998ef1eb9f82a7d3ce9b4a97dba5aa13Ivo van Doorn
1260dec13b6bda600c7e7da993e634562873112af50bIvo van Doorn	rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
126119d30e02998ef1eb9f82a7d3ce9b4a97dba5aa13Ivo van Doorn	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
126219d30e02998ef1eb9f82a7d3ce9b4a97dba5aa13Ivo van Doorn		rxdesc->dev_flags |= RXDONE_MY_BSS;
126395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
126495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
126595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
126695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Interrupt functions.
126795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
1268181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
1269e58c6aca99357d7f85f18e0b661d8c5a87f926a9Ivo van Doorn			     const enum data_queue_qid queue_idx)
127095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
127161c6e4893f3070b6473ca4ec3176c7471d44278bGertjan van Wingerde	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
1272b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	struct queue_entry_priv_pci *entry_priv;
1273181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	struct queue_entry *entry;
1274181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	struct txdone_entry_desc txdesc;
127595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 word;
127695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1277181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	while (!rt2x00queue_empty(queue)) {
1278181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
1279b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn		entry_priv = entry->priv_data;
1280b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
128195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
128295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
128395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		    !rt2x00_get_field32(word, TXD_W0_VALID))
128495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			break;
128595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
128695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		/*
128795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		 * Obtain the status about this packet.
128895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		 */
1289fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		txdesc.flags = 0;
1290fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
1291fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		case 0: /* Success */
1292fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		case 1: /* Success with retry */
1293fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn			__set_bit(TXDONE_SUCCESS, &txdesc.flags);
1294fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn			break;
1295fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		case 2: /* Failure, excessive retries */
1296fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn			__set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
1297fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn			/* Don't break, this is a failed frame! */
1298fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		default: /* Failure */
1299fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn			__set_bit(TXDONE_FAILURE, &txdesc.flags);
1300fb55f4d1fa252ba1e479284b79da1049d658c371Ivo van Doorn		}
1301181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn		txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
130295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1303e513a0b6f1bf8e1b59b0e1382d4e7ef3d344d535Gertjan van Wingerde		rt2x00lib_txdone(entry, &txdesc);
130495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
130595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
130695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
13077a5a681a7df7d844b52f82a4388e078071eb883eHelmut Schaastatic inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
13087a5a681a7df7d844b52f82a4388e078071eb883eHelmut Schaa					      struct rt2x00_field32 irq_field)
130995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
1310bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	u32 reg;
131195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
131295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1313bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * Enable a single interrupt. The interrupt mask register
1314bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * access needs locking.
131595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
13160aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_lock_irq(&rt2x00dev->irqmask_lock);
131795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1318bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
1319bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00_set_field32(&reg, irq_field, 0);
1320bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
132195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
13220aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_unlock_irq(&rt2x00dev->irqmask_lock);
1323bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa}
132495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1325bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaastatic void rt2400pci_txstatus_tasklet(unsigned long data)
1326bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa{
1327bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1328bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	u32 reg;
132995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
133095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1331bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * Handle all tx queues.
133295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1333bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2400pci_txdone(rt2x00dev, QID_ATIM);
1334bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2400pci_txdone(rt2x00dev, QID_AC_VO);
1335bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2400pci_txdone(rt2x00dev, QID_AC_VI);
133695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
133795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1338bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * Enable all TXDONE interrupts again.
133995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1340abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
1341abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		spin_lock_irq(&rt2x00dev->irqmask_lock);
134295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1343abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
1344abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
1345abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
1346abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
1347abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2x00pci_register_write(rt2x00dev, CSR8, reg);
1348bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1349abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		spin_unlock_irq(&rt2x00dev->irqmask_lock);
1350abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	}
1351bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa}
1352bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1353bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaastatic void rt2400pci_tbtt_tasklet(unsigned long data)
1354bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa{
1355bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1356bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00lib_beacondone(rt2x00dev);
1357abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1358abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
1359bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa}
1360bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1361bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaastatic void rt2400pci_rxdone_tasklet(unsigned long data)
1362bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa{
1363bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1364166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa	if (rt2x00pci_rxdone(rt2x00dev))
1365166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
1366abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1367166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa		rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
136895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
136995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
137078e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaastatic irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
137178e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa{
137278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	struct rt2x00_dev *rt2x00dev = dev_instance;
1373bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	u32 reg, mask;
137478e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
137578e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	/*
137678e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	 * Get the interrupt sources & saved to local variable.
137778e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	 * Write register value back to clear pending interrupts.
137878e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	 */
137978e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
138078e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	rt2x00pci_register_write(rt2x00dev, CSR7, reg);
138178e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
138278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	if (!reg)
138378e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa		return IRQ_NONE;
138478e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
138578e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
138678e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa		return IRQ_HANDLED;
138778e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
1388bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	mask = reg;
1389bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1390bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	/*
1391bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * Schedule tasklets for interrupt handling.
1392bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 */
1393bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
1394bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
1395bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1396bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	if (rt2x00_get_field32(reg, CSR7_RXDONE))
1397bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
1398bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1399bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
1400bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
1401bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
1402bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
1403bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		/*
1404bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 * Mask out all txdone interrupts.
1405bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		 */
1406bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
1407bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
1408bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
1409bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	}
141078e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
1411bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	/*
1412bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * Disable all interrupts for which a tasklet was scheduled right now,
1413bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 * the tasklet will reenable the appropriate interrupts.
1414bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	 */
14150aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_lock(&rt2x00dev->irqmask_lock);
141678e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
1417bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
1418bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	reg |= mask;
1419bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
1420bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
14210aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_unlock(&rt2x00dev->irqmask_lock);
1422bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1423bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1424bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa
1425bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	return IRQ_HANDLED;
142678e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa}
142778e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
142895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
142995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Device probe functions.
143095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
143195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
143295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
143395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct eeprom_93cx6 eeprom;
143495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
143595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u16 word;
143695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u8 *mac;
143795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
143895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
143995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
144095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.data = rt2x00dev;
144195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.register_read = rt2400pci_eepromregister_read;
144295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.register_write = rt2400pci_eepromregister_write;
144395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?
144495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	    PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
144595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.reg_data_in = 0;
144695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.reg_data_out = 0;
144795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.reg_data_clock = 0;
144895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom.reg_chip_select = 0;
144995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
145095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
145195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			       EEPROM_SIZE / sizeof(u16));
145295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
145395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
145495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Start validation of the data that has been read.
145595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
145695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
145795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (!is_valid_ether_addr(mac)) {
145895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		random_ether_addr(mac);
1459e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
146095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
146195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
146295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
146395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (word == 0xffff) {
146495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		ERROR(rt2x00dev, "Invalid EEPROM data detected.\n");
146595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -EINVAL;
146695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
146795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
146895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
146995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
147095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
147195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
147295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
147395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
147495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u16 value;
147595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u16 eeprom;
147695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
147795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
147895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Read EEPROM word for configuration.
147995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
148095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
148195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
148295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
148395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Identify RF chipset.
148495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
148595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
148695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
148749e721ec6ca74f90ee99089ad2de1c338a95c6d5Gertjan van Wingerde	rt2x00_set_chip(rt2x00dev, RT2460, value,
148849e721ec6ca74f90ee99089ad2de1c338a95c6d5Gertjan van Wingerde			rt2x00_get_field32(reg, CSR0_REVISION));
148995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
14905122d8986232ef2a761f5cf70c31666c4d65c3e4Gertjan van Wingerde	if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
149195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
149295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -ENODEV;
149395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	}
149495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
149595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
149695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Identify default antenna configuration.
149795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1498addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	rt2x00dev->default_ant.tx =
149995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
1500addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	rt2x00dev->default_ant.rx =
150195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
150295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
150395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1504addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	 * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
1505addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	 * I am not 100% sure about this, but the legacy drivers do not
1506addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	 * indicate antenna swapping in software is required when
1507addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	 * diversity is enabled.
1508addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	 */
1509addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
1510addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn		rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
1511addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
1512addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn		rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
1513addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn
1514addc81bd428f9eb29ed2ab64ad4039c6aed55aeaIvo van Doorn	/*
151595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Store led mode, for correct led behaviour.
151695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1517771fd565195727d12f0b75d918b9fcb9f33a5476Ivo van Doorn#ifdef CONFIG_RT2X00_LIB_LEDS
1518a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
1519a9450b70a755abf093600035ef5361c53343fe9aIvo van Doorn
1520475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn	rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
15213d3e451ff71b4e951d4b522b460a94f36fb5b276Ivo van Doorn	if (value == LED_MODE_TXRX_ACTIVITY ||
15223d3e451ff71b4e951d4b522b460a94f36fb5b276Ivo van Doorn	    value == LED_MODE_DEFAULT ||
15233d3e451ff71b4e951d4b522b460a94f36fb5b276Ivo van Doorn	    value == LED_MODE_ASUS)
1524475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn		rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
1525475433be3d8f4d840e2930eef96671b7f8d11053Ivo van Doorn				   LED_TYPE_ACTIVITY);
1526771fd565195727d12f0b75d918b9fcb9f33a5476Ivo van Doorn#endif /* CONFIG_RT2X00_LIB_LEDS */
152795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
152895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
152995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Detect if this device has an hardware controlled radio.
153095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
153195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
15327dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
153395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
153495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
153595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Check if the BBP tuning should be enabled.
153695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
153727df2a9ce9ea6a77b9959cf5cc03ee85324aced9Ivo van Doorn	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
15387dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
153995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
154095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
154195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
154295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
154395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
154495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * RF value list for RF2420 & RF2421
154595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Supports: 2.4 GHz
154695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
15478c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doornstatic const struct rf_channel rf_vals_b[] = {
154895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 1,  0x00022058, 0x000c1fda, 0x00000101, 0 },
154995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 2,  0x00022058, 0x000c1fee, 0x00000101, 0 },
155095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 3,  0x00022058, 0x000c2002, 0x00000101, 0 },
155195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 4,  0x00022058, 0x000c2016, 0x00000101, 0 },
155295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 5,  0x00022058, 0x000c202a, 0x00000101, 0 },
155395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 6,  0x00022058, 0x000c203e, 0x00000101, 0 },
155495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 7,  0x00022058, 0x000c2052, 0x00000101, 0 },
155595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 8,  0x00022058, 0x000c2066, 0x00000101, 0 },
155695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 9,  0x00022058, 0x000c207a, 0x00000101, 0 },
155795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 10, 0x00022058, 0x000c208e, 0x00000101, 0 },
155895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 11, 0x00022058, 0x000c20a2, 0x00000101, 0 },
155995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 12, 0x00022058, 0x000c20b6, 0x00000101, 0 },
156095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 13, 0x00022058, 0x000c20ca, 0x00000101, 0 },
156195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 14, 0x00022058, 0x000c20fa, 0x00000101, 0 },
156295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
156395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
15648c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doornstatic int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
156595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
156695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct hw_mode_spec *spec = &rt2x00dev->spec;
15678c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	struct channel_info *info;
15688c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	char *tx_power;
156995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	unsigned int i;
157095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
157195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
157295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Initialize all hw fields.
157395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1574566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
15754be8c3873e0b88397866d3ede578503e188f9ad2Johannes Berg			       IEEE80211_HW_SIGNAL_DBM |
15764be8c3873e0b88397866d3ede578503e188f9ad2Johannes Berg			       IEEE80211_HW_SUPPORTS_PS |
15774be8c3873e0b88397866d3ede578503e188f9ad2Johannes Berg			       IEEE80211_HW_PS_NULLFUNC_STACK;
157895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
157914a3bf89212b5c758bd39bb4afc972c4ba6d599fGertjan van Wingerde	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
158095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
158195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn				rt2x00_eeprom_addr(rt2x00dev,
158295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn						   EEPROM_MAC_ADDR_0));
158395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
158495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
158595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Initialize hw_mode information.
158695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
158731562e802a72caf0757f351fff563d558d48d087Ivo van Doorn	spec->supported_bands = SUPPORT_BAND_2GHZ;
158831562e802a72caf0757f351fff563d558d48d087Ivo van Doorn	spec->supported_rates = SUPPORT_RATE_CCK;
158995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
15908c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	spec->num_channels = ARRAY_SIZE(rf_vals_b);
15918c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	spec->channels = rf_vals_b;
15928c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn
15938c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	/*
15948c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	 * Create channel information array
15958c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	 */
1596baeb2ffab4e67bb9174e6166e070a9a8ec94b0f6Joe Perches	info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
15978c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	if (!info)
15988c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn		return -ENOMEM;
15998c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn
16008c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	spec->channels_info = info;
16018c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn
16028c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
16038d1331b37d5b656a7a8e561f8e9d7661dd00c910Ivo van Doorn	for (i = 0; i < 14; i++) {
16048d1331b37d5b656a7a8e561f8e9d7661dd00c910Ivo van Doorn		info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
16058d1331b37d5b656a7a8e561f8e9d7661dd00c910Ivo van Doorn		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
16068d1331b37d5b656a7a8e561f8e9d7661dd00c910Ivo van Doorn	}
16078c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn
16088c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	return 0;
160995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
161095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
161195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
161295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
161395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	int retval;
161495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
161595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
161695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Allocate eeprom data.
161795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
161895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	retval = rt2400pci_validate_eeprom(rt2x00dev);
161995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (retval)
162095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return retval;
162195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
162295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	retval = rt2400pci_init_eeprom(rt2x00dev);
162395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	if (retval)
162495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return retval;
162595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
162695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
162795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Initialize hw specifications.
162895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
16298c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	retval = rt2400pci_probe_hw_mode(rt2x00dev);
16308c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn	if (retval)
16318c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn		return retval;
163295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
163395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
1634c4da004857056e6ee034c4110ccdcba659077b7eGertjan van Wingerde	 * This device requires the atim queue and DMA-mapped skbs.
163595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
16367dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
16377dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
16387dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
163995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
164095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
164195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Set the rssi offset.
164295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
164395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
164495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
164595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
164695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
164795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
164895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
164995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * IEEE80211 stack callback functions.
165095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
16518a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Pellerstatic int rt2400pci_conf_tx(struct ieee80211_hw *hw,
16528a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Peller			     struct ieee80211_vif *vif, u16 queue,
165395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn			     const struct ieee80211_tx_queue_params *params)
165495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
165595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct rt2x00_dev *rt2x00dev = hw->priv;
165695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
165795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
165895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * We don't support variating cw_min and cw_max variables
165995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * per queue. So by default we only configure the TX queue,
166095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * and ignore all other configurations.
166195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1662e100bb64bf7cdeae7f742a65ee1985649a7fd1b4Johannes Berg	if (queue != 0)
166395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -EINVAL;
166495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
16658a3a3c85e44d58f5af0adac74a0b866ba89a1978Eliad Peller	if (rt2x00mac_conf_tx(hw, vif, queue, params))
166695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn		return -EINVAL;
166795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
166895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	/*
166995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 * Write configuration to register.
167095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	 */
1671181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	rt2400pci_config_cw(rt2x00dev,
1672181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn			    rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
167395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
167495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return 0;
167595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
167695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
167737a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Pellerstatic u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
167837a41b4affa33bb237d3692bf51f1b5ebcaf29d8Eliad Peller			     struct ieee80211_vif *vif)
167995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
168095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct rt2x00_dev *rt2x00dev = hw->priv;
168195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u64 tsf;
168295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
168395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
168495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR17, &reg);
168595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
168695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR16, &reg);
168795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
168895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
168995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return tsf;
169095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
169195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
169295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
169395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
169495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	struct rt2x00_dev *rt2x00dev = hw->priv;
169595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	u32 reg;
169695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
169795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	rt2x00pci_register_read(rt2x00dev, CSR15, &reg);
169895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
169995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
170095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
170195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic const struct ieee80211_ops rt2400pci_mac80211_ops = {
170295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.tx			= rt2x00mac_tx,
17034150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	.start			= rt2x00mac_start,
17044150c57212ad134765dd78c654a4b9906252b66dJohannes Berg	.stop			= rt2x00mac_stop,
170595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.add_interface		= rt2x00mac_add_interface,
170695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.remove_interface	= rt2x00mac_remove_interface,
170795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.config			= rt2x00mac_config,
17083a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	.configure_filter	= rt2x00mac_configure_filter,
1709d8147f9d9ed6abfa105234a21f05af4a4839eb80Ivo van Doorn	.sw_scan_start		= rt2x00mac_sw_scan_start,
1710d8147f9d9ed6abfa105234a21f05af4a4839eb80Ivo van Doorn	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
171195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.get_stats		= rt2x00mac_get_stats,
1712471b3efdfccc257591331724145f8ccf8b3217e1Johannes Berg	.bss_info_changed	= rt2x00mac_bss_info_changed,
171395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.conf_tx		= rt2400pci_conf_tx,
171495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.get_tsf		= rt2400pci_get_tsf,
171595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.tx_last_beacon		= rt2400pci_tx_last_beacon,
1716e47a5cddf893815e7da16e3226b959af785d8aafIvo van Doorn	.rfkill_poll		= rt2x00mac_rfkill_poll,
1717f44df18c58d4debe3ec0bb76a490aa2f3929fd8bIvo van Doorn	.flush			= rt2x00mac_flush,
17180ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn	.set_antenna		= rt2x00mac_set_antenna,
17190ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn	.get_antenna		= rt2x00mac_get_antenna,
1720e7dee444263a103a9a2ac5fd5d0b5e9dc177d57cIvo van Doorn	.get_ringparam		= rt2x00mac_get_ringparam,
17215f0dd296a01c8173fcc05a8b262a1168ae90bc74Gertjan van Wingerde	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
172295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
172395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
172495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
172595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.irq_handler		= rt2400pci_interrupt,
1726bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	.txstatus_tasklet	= rt2400pci_txstatus_tasklet,
1727bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	.tbtt_tasklet		= rt2400pci_tbtt_tasklet,
1728bcf3cfd047d599cd0e6758c422bd7a4835c00d4aHelmut Schaa	.rxdone_tasklet		= rt2400pci_rxdone_tasklet,
172995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.probe_hw		= rt2400pci_probe_hw,
173095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.initialize		= rt2x00pci_initialize,
173195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.uninitialize		= rt2x00pci_uninitialize,
1732798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	.get_entry_state	= rt2400pci_get_entry_state,
1733798b7adb4ed3533ab1282f51d16892034cfd8aaeIvo van Doorn	.clear_entry		= rt2400pci_clear_entry,
173495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.set_device_state	= rt2400pci_set_device_state,
173595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.rfkill_poll		= rt2400pci_rfkill_poll,
173695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.link_stats		= rt2400pci_link_stats,
173795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.reset_tuner		= rt2400pci_reset_tuner,
173895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.link_tuner		= rt2400pci_link_tuner,
1739dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.start_queue		= rt2400pci_start_queue,
1740dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.kick_queue		= rt2400pci_kick_queue,
1741dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.stop_queue		= rt2400pci_stop_queue,
1742152a599274b15028604e24ae2d9c9d7f49853977Ivo van Doorn	.flush_queue		= rt2x00pci_flush_queue,
174395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.write_tx_desc		= rt2400pci_write_tx_desc,
1744bd88a7812f1afd50549f3789cacb707b983fef54Ivo van Doorn	.write_beacon		= rt2400pci_write_beacon,
174595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.fill_rxdone		= rt2400pci_fill_rxdone,
17463a643d244f09fa1fdd25d48a56a073c1a69583eeIvo van Doorn	.config_filter		= rt2400pci_config_filter,
17476bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn	.config_intf		= rt2400pci_config_intf,
1748728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn	.config_erp		= rt2400pci_config_erp,
1749e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn	.config_ant		= rt2400pci_config_ant,
175095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.config			= rt2400pci_config,
175195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
175295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1753181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic const struct data_queue_desc rt2400pci_queue_rx = {
1754efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 24,
1755181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.data_size		= DATA_FRAME_SIZE,
1756181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.desc_size		= RXD_DESC_SIZE,
1757b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1758181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn};
1759181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn
1760181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic const struct data_queue_desc rt2400pci_queue_tx = {
1761efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 24,
1762181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.data_size		= DATA_FRAME_SIZE,
1763181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.desc_size		= TXD_DESC_SIZE,
1764b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1765181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn};
1766181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn
1767181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic const struct data_queue_desc rt2400pci_queue_bcn = {
1768efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 1,
1769181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.data_size		= MGMT_FRAME_SIZE,
1770181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.desc_size		= TXD_DESC_SIZE,
1771b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1772181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn};
1773181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn
1774181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doornstatic const struct data_queue_desc rt2400pci_queue_atim = {
1775efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 8,
1776181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.data_size		= DATA_FRAME_SIZE,
1777181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn	.desc_size		= TXD_DESC_SIZE,
1778b8be63ffa5dc44324e7f507997870fa3e4b17619Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1779181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn};
1780181d6902b6bad978d157e69479c95cc0ff213a76Ivo van Doorn
178195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic const struct rt2x00_ops rt2400pci_ops = {
178204d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.name			= KBUILD_MODNAME,
178304d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.max_sta_intf		= 1,
178404d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.max_ap_intf		= 1,
178504d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.eeprom_size		= EEPROM_SIZE,
178604d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.rf_size		= RF_SIZE,
178704d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.tx_queues		= NUM_TX_QUEUES,
1788e6218cc47bd54710dc523e8c983ceddba625e3aeGertjan van Wingerde	.extra_tx_headroom	= 0,
178904d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.rx			= &rt2400pci_queue_rx,
179004d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.tx			= &rt2400pci_queue_tx,
179104d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.bcn			= &rt2400pci_queue_bcn,
179204d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.atim			= &rt2400pci_queue_atim,
179304d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.lib			= &rt2400pci_rt2x00_ops,
179404d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.hw			= &rt2400pci_mac80211_ops,
179595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#ifdef CONFIG_RT2X00_LIB_DEBUGFS
179604d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.debugfs		= &rt2400pci_rt2x00debug,
179795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
179895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
179995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
180095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/*
180195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * RT2400pci module information.
180295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */
1803a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
1804e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x0101) },
180595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	{ 0, }
180695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
180795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1808e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde
180995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_AUTHOR(DRV_PROJECT);
181095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_VERSION(DRV_VERSION);
181195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
181295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
181395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
181495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van DoornMODULE_LICENSE("GPL");
181595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
1816e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerdestatic int rt2400pci_probe(struct pci_dev *pci_dev,
1817e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde			   const struct pci_device_id *id)
1818e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde{
1819e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
1820e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde}
1821e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde
182295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic struct pci_driver rt2400pci_driver = {
18232360157c413b06fe2958a051daeab7bac68f6588Ivo van Doorn	.name		= KBUILD_MODNAME,
182495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.id_table	= rt2400pci_device_table,
1825e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	.probe		= rt2400pci_probe,
182695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.remove		= __devexit_p(rt2x00pci_remove),
182795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.suspend	= rt2x00pci_suspend,
182895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	.resume		= rt2x00pci_resume,
182995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn};
183095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
183195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic int __init rt2400pci_init(void)
183295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
183395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	return pci_register_driver(&rt2400pci_driver);
183495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
183595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
183695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornstatic void __exit rt2400pci_exit(void)
183795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{
183895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn	pci_unregister_driver(&rt2400pci_driver);
183995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn}
184095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn
184195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornmodule_init(rt2400pci_init);
184295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doornmodule_exit(rt2400pci_exit);
1843