diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2007-08-12 11:33:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:35 -0500 |
commit | fa1c114fdaa605496045e56c42d0c8aa4c139e57 (patch) | |
tree | df8345d8ef17cea23da3c0bbe388729b79920bfe /drivers/net/wireless/ath5k | |
parent | 3543f8069d3cc932202e64095d1d3986a10d34ed (diff) |
[PATCH] Net: add ath5k wireless driver
add ath5k wireless driver
Portions of this driver are covered by one or both of the ISC and
3-clause BSD licenses. Specific license information is cited at the top
of each file.
Acked-by and Signed-off-by information is collected from individual
patches as collected in the wireless-2.6 tree prior to upstream
submission.
Acked-by: Matthew W. S. Bell <mentor@madwifi.org>
Acked-by: Michael Taylor <mike.taylor@apprion.com>
Acked-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Bradley M. Kuhn <bkuhn@softwarefreedom.org>
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
Signed-off-by: Dave Young <hidave.darkstar@gmail.com>
Signed-off-by: Francesco Gringoli <francesco.gringoli@ing.unibs.it>
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Karen Sandler <karen@softwarefreedom.org>
Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
Signed-off-by: Matt Norwood <norwood@softwarefreedom.org>
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: Richard Fontana <fontana@softwarefreedom.org>
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Ulrich Meis <meis@nets.rwth-aachen.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k')
-rw-r--r-- | drivers/net/wireless/ath5k/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/ath5k.h | 1173 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 2817 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.h | 178 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/debug.c | 469 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/debug.h | 216 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/hw.c | 4349 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/hw.h | 588 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/initvals.c | 1347 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/phy.c | 2071 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/reg.h | 1987 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/regdom.c | 121 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/regdom.h | 500 |
13 files changed, 15818 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile new file mode 100644 index 000000000000..321641f99e13 --- /dev/null +++ b/drivers/net/wireless/ath5k/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o | ||
2 | obj-$(CONFIG_ATH5K) += ath5k.o | ||
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h new file mode 100644 index 000000000000..878609f1bf39 --- /dev/null +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -0,0 +1,1173 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef _ATH5K_H | ||
19 | #define _ATH5K_H | ||
20 | |||
21 | /* Set this to 1 to disable regulatory domain restrictions for channel tests. | ||
22 | * WARNING: This is for debuging only and has side effects (eg. scan takes too | ||
23 | * long and results timeouts). It's also illegal to tune to some of the | ||
24 | * supported frequencies in some countries, so use this at your own risk, | ||
25 | * you've been warned. */ | ||
26 | #define CHAN_DEBUG 0 | ||
27 | |||
28 | #include <linux/io.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <net/mac80211.h> | ||
31 | |||
32 | #include "hw.h" | ||
33 | #include "regdom.h" | ||
34 | |||
35 | /* PCI IDs */ | ||
36 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ | ||
37 | #define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */ | ||
38 | #define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */ | ||
39 | #define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */ | ||
40 | #define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */ | ||
41 | #define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */ | ||
42 | #define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */ | ||
43 | #define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */ | ||
44 | #define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */ | ||
45 | #define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */ | ||
46 | #define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */ | ||
47 | #define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */ | ||
48 | #define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */ | ||
49 | #define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */ | ||
50 | #define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ | ||
51 | #define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ | ||
52 | #define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */ | ||
53 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */ | ||
54 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */ | ||
55 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */ | ||
56 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */ | ||
57 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */ | ||
58 | #define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */ | ||
59 | #define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */ | ||
60 | #define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */ | ||
61 | #define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */ | ||
62 | #define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */ | ||
63 | #define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */ | ||
64 | |||
65 | /****************************\ | ||
66 | GENERIC DRIVER DEFINITIONS | ||
67 | \****************************/ | ||
68 | |||
69 | #define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__) | ||
70 | |||
71 | #define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ | ||
72 | printk(_level "ath5k %s: " _fmt, \ | ||
73 | ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \ | ||
74 | ##__VA_ARGS__) | ||
75 | |||
76 | #define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \ | ||
77 | if (net_ratelimit()) \ | ||
78 | ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ | ||
79 | } while (0) | ||
80 | |||
81 | #define ATH5K_INFO(_sc, _fmt, ...) \ | ||
82 | ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) | ||
83 | |||
84 | #define ATH5K_WARN(_sc, _fmt, ...) \ | ||
85 | ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) | ||
86 | |||
87 | #define ATH5K_ERR(_sc, _fmt, ...) \ | ||
88 | ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) | ||
89 | |||
90 | /* | ||
91 | * Some tuneable values (these should be changeable by the user) | ||
92 | */ | ||
93 | #define AR5K_TUNE_DMA_BEACON_RESP 2 | ||
94 | #define AR5K_TUNE_SW_BEACON_RESP 10 | ||
95 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 | ||
96 | #define AR5K_TUNE_RADAR_ALERT false | ||
97 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 | ||
98 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) | ||
99 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 | ||
100 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to | ||
101 | * be the max value. */ | ||
102 | #define AR5K_TUNE_RSSI_THRES 129 | ||
103 | /* This must be set when setting the RSSI threshold otherwise it can | ||
104 | * prevent a reset. If AR5K_RSSI_THR is read after writing to it | ||
105 | * the BMISS_THRES will be seen as 0, seems harware doesn't keep | ||
106 | * track of it. Max value depends on harware. For AR5210 this is just 7. | ||
107 | * For AR5211+ this seems to be up to 255. */ | ||
108 | #define AR5K_TUNE_BMISS_THRES 7 | ||
109 | #define AR5K_TUNE_REGISTER_DWELL_TIME 20000 | ||
110 | #define AR5K_TUNE_BEACON_INTERVAL 100 | ||
111 | #define AR5K_TUNE_AIFS 2 | ||
112 | #define AR5K_TUNE_AIFS_11B 2 | ||
113 | #define AR5K_TUNE_AIFS_XR 0 | ||
114 | #define AR5K_TUNE_CWMIN 15 | ||
115 | #define AR5K_TUNE_CWMIN_11B 31 | ||
116 | #define AR5K_TUNE_CWMIN_XR 3 | ||
117 | #define AR5K_TUNE_CWMAX 1023 | ||
118 | #define AR5K_TUNE_CWMAX_11B 1023 | ||
119 | #define AR5K_TUNE_CWMAX_XR 7 | ||
120 | #define AR5K_TUNE_NOISE_FLOOR -72 | ||
121 | #define AR5K_TUNE_MAX_TXPOWER 60 | ||
122 | #define AR5K_TUNE_DEFAULT_TXPOWER 30 | ||
123 | #define AR5K_TUNE_TPC_TXPOWER true | ||
124 | #define AR5K_TUNE_ANT_DIVERSITY true | ||
125 | #define AR5K_TUNE_HWTXTRIES 4 | ||
126 | |||
127 | /* token to use for aifs, cwmin, cwmax in MadWiFi */ | ||
128 | #define AR5K_TXQ_USEDEFAULT ((u32) -1) | ||
129 | |||
130 | /* GENERIC CHIPSET DEFINITIONS */ | ||
131 | |||
132 | /* MAC Chips */ | ||
133 | enum ath5k_version { | ||
134 | AR5K_AR5210 = 0, | ||
135 | AR5K_AR5211 = 1, | ||
136 | AR5K_AR5212 = 2, | ||
137 | }; | ||
138 | |||
139 | /* PHY Chips */ | ||
140 | enum ath5k_radio { | ||
141 | AR5K_RF5110 = 0, | ||
142 | AR5K_RF5111 = 1, | ||
143 | AR5K_RF5112 = 2, | ||
144 | AR5K_RF5413 = 3, | ||
145 | }; | ||
146 | |||
147 | /* | ||
148 | * Common silicon revision/version values | ||
149 | */ | ||
150 | |||
151 | enum ath5k_srev_type { | ||
152 | AR5K_VERSION_VER, | ||
153 | AR5K_VERSION_RAD, | ||
154 | }; | ||
155 | |||
156 | struct ath5k_srev_name { | ||
157 | const char *sr_name; | ||
158 | enum ath5k_srev_type sr_type; | ||
159 | u_int sr_val; | ||
160 | }; | ||
161 | |||
162 | #define AR5K_SREV_UNKNOWN 0xffff | ||
163 | |||
164 | #define AR5K_SREV_VER_AR5210 0x00 | ||
165 | #define AR5K_SREV_VER_AR5311 0x10 | ||
166 | #define AR5K_SREV_VER_AR5311A 0x20 | ||
167 | #define AR5K_SREV_VER_AR5311B 0x30 | ||
168 | #define AR5K_SREV_VER_AR5211 0x40 | ||
169 | #define AR5K_SREV_VER_AR5212 0x50 | ||
170 | #define AR5K_SREV_VER_AR5213 0x55 | ||
171 | #define AR5K_SREV_VER_AR5213A 0x59 | ||
172 | #define AR5K_SREV_VER_AR2424 0xa0 | ||
173 | #define AR5K_SREV_VER_AR5424 0xa3 | ||
174 | #define AR5K_SREV_VER_AR5413 0xa4 | ||
175 | #define AR5K_SREV_VER_AR5414 0xa5 | ||
176 | #define AR5K_SREV_VER_AR5416 0xc0 /* ? */ | ||
177 | #define AR5K_SREV_VER_AR5418 0xca | ||
178 | |||
179 | #define AR5K_SREV_RAD_5110 0x00 | ||
180 | #define AR5K_SREV_RAD_5111 0x10 | ||
181 | #define AR5K_SREV_RAD_5111A 0x15 | ||
182 | #define AR5K_SREV_RAD_2111 0x20 | ||
183 | #define AR5K_SREV_RAD_5112 0x30 | ||
184 | #define AR5K_SREV_RAD_5112A 0x35 | ||
185 | #define AR5K_SREV_RAD_2112 0x40 | ||
186 | #define AR5K_SREV_RAD_2112A 0x45 | ||
187 | #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ | ||
188 | #define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */ | ||
189 | #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ | ||
190 | |||
191 | /* IEEE defs */ | ||
192 | |||
193 | #define IEEE80211_MAX_LEN 2500 | ||
194 | |||
195 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | ||
196 | |||
197 | /* | ||
198 | * Some of this information is based on Documentation from: | ||
199 | * | ||
200 | * http://madwifi.org/wiki/ChipsetFeatures/SuperAG | ||
201 | * | ||
202 | * Modulation for Atheros' eXtended Range - range enhancing extension that is | ||
203 | * supposed to double the distance an Atheros client device can keep a | ||
204 | * connection with an Atheros access point. This is achieved by increasing | ||
205 | * the receiver sensitivity up to, -105dBm, which is about 20dB above what | ||
206 | * the 802.11 specifications demand. In addition, new (proprietary) data rates | ||
207 | * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. | ||
208 | * | ||
209 | * Please note that can you either use XR or TURBO but you cannot use both, | ||
210 | * they are exclusive. | ||
211 | * | ||
212 | */ | ||
213 | #define MODULATION_XR 0x00000200 | ||
214 | /* | ||
215 | * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a | ||
216 | * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s | ||
217 | * signaling rate achieved through the bonding of two 54Mbit/s 802.11g | ||
218 | * channels. To use this feature your Access Point must also suport it. | ||
219 | * There is also a distinction between "static" and "dynamic" turbo modes: | ||
220 | * | ||
221 | * - Static: is the dumb version: devices set to this mode stick to it until | ||
222 | * the mode is turned off. | ||
223 | * - Dynamic: is the intelligent version, the network decides itself if it | ||
224 | * is ok to use turbo. As soon as traffic is detected on adjacent channels | ||
225 | * (which would get used in turbo mode), or when a non-turbo station joins | ||
226 | * the network, turbo mode won't be used until the situation changes again. | ||
227 | * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which | ||
228 | * monitors the used radio band in order to decide whether turbo mode may | ||
229 | * be used or not. | ||
230 | * | ||
231 | * This article claims Super G sticks to bonding of channels 5 and 6 for | ||
232 | * USA: | ||
233 | * | ||
234 | * http://www.pcworld.com/article/id,113428-page,1/article.html | ||
235 | * | ||
236 | * The channel bonding seems to be driver specific though. In addition to | ||
237 | * deciding what channels will be used, these "Turbo" modes are accomplished | ||
238 | * by also enabling the following features: | ||
239 | * | ||
240 | * - Bursting: allows multiple frames to be sent at once, rather than pausing | ||
241 | * after each frame. Bursting is a standards-compliant feature that can be | ||
242 | * used with any Access Point. | ||
243 | * - Fast frames: increases the amount of information that can be sent per | ||
244 | * frame, also resulting in a reduction of transmission overhead. It is a | ||
245 | * proprietary feature that needs to be supported by the Access Point. | ||
246 | * - Compression: data frames are compressed in real time using a Lempel Ziv | ||
247 | * algorithm. This is done transparently. Once this feature is enabled, | ||
248 | * compression and decompression takes place inside the chipset, without | ||
249 | * putting additional load on the host CPU. | ||
250 | * | ||
251 | */ | ||
252 | #define MODULATION_TURBO 0x00000080 | ||
253 | |||
254 | enum ath5k_vendor_mode { | ||
255 | MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1, | ||
256 | MODE_ATHEROS_TURBOG | ||
257 | }; | ||
258 | |||
259 | /* Number of supported mac80211 enum ieee80211_phymode modes by this driver */ | ||
260 | #define NUM_DRIVER_MODES 3 | ||
261 | |||
262 | /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */ | ||
263 | #define AR5K_SET_SHORT_PREAMBLE 0x04 | ||
264 | |||
265 | #define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2) | ||
266 | #define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) | ||
267 | |||
268 | /****************\ | ||
269 | TX DEFINITIONS | ||
270 | \****************/ | ||
271 | |||
272 | /* | ||
273 | * Tx Descriptor | ||
274 | */ | ||
275 | struct ath5k_tx_status { | ||
276 | u16 ts_seqnum; | ||
277 | u16 ts_tstamp; | ||
278 | u8 ts_status; | ||
279 | u8 ts_rate; | ||
280 | s8 ts_rssi; | ||
281 | u8 ts_shortretry; | ||
282 | u8 ts_longretry; | ||
283 | u8 ts_virtcol; | ||
284 | u8 ts_antenna; | ||
285 | }; | ||
286 | |||
287 | #define AR5K_TXSTAT_ALTRATE 0x80 | ||
288 | #define AR5K_TXERR_XRETRY 0x01 | ||
289 | #define AR5K_TXERR_FILT 0x02 | ||
290 | #define AR5K_TXERR_FIFO 0x04 | ||
291 | |||
292 | /** | ||
293 | * enum ath5k_tx_queue - Queue types used to classify tx queues. | ||
294 | * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue | ||
295 | * @AR5K_TX_QUEUE_DATA: A normal data queue | ||
296 | * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue | ||
297 | * @AR5K_TX_QUEUE_BEACON: The beacon queue | ||
298 | * @AR5K_TX_QUEUE_CAB: The after-beacon queue | ||
299 | * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue | ||
300 | */ | ||
301 | enum ath5k_tx_queue { | ||
302 | AR5K_TX_QUEUE_INACTIVE = 0, | ||
303 | AR5K_TX_QUEUE_DATA, | ||
304 | AR5K_TX_QUEUE_XR_DATA, | ||
305 | AR5K_TX_QUEUE_BEACON, | ||
306 | AR5K_TX_QUEUE_CAB, | ||
307 | AR5K_TX_QUEUE_UAPSD, | ||
308 | }; | ||
309 | |||
310 | #define AR5K_NUM_TX_QUEUES 10 | ||
311 | #define AR5K_NUM_TX_QUEUES_NOQCU 2 | ||
312 | |||
313 | /* | ||
314 | * Queue syb-types to classify normal data queues. | ||
315 | * These are the 4 Access Categories as defined in | ||
316 | * WME spec. 0 is the lowest priority and 4 is the | ||
317 | * highest. Normal data that hasn't been classified | ||
318 | * goes to the Best Effort AC. | ||
319 | */ | ||
320 | enum ath5k_tx_queue_subtype { | ||
321 | AR5K_WME_AC_BK = 0, /*Background traffic*/ | ||
322 | AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/ | ||
323 | AR5K_WME_AC_VI, /*Video traffic*/ | ||
324 | AR5K_WME_AC_VO, /*Voice traffic*/ | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | * Queue ID numbers as returned by the hw functions, each number | ||
329 | * represents a hw queue. If hw does not support hw queues | ||
330 | * (eg 5210) all data goes in one queue. These match | ||
331 | * d80211 definitions (net80211/MadWiFi don't use them). | ||
332 | */ | ||
333 | enum ath5k_tx_queue_id { | ||
334 | AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, | ||
335 | AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, | ||
336 | AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ | ||
337 | AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/ | ||
338 | AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ | ||
339 | AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ | ||
340 | AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ | ||
341 | AR5K_TX_QUEUE_ID_UAPSD = 8, | ||
342 | AR5K_TX_QUEUE_ID_XR_DATA = 9, | ||
343 | }; | ||
344 | |||
345 | |||
346 | /* | ||
347 | * Flags to set hw queue's parameters... | ||
348 | */ | ||
349 | #define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */ | ||
350 | #define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */ | ||
351 | #define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */ | ||
352 | #define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */ | ||
353 | #define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */ | ||
354 | #define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0020 /* Disable random post-backoff */ | ||
355 | #define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0040 /* Enable ready time expiry policy (?)*/ | ||
356 | #define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0080 /* Enable backoff while bursting */ | ||
357 | #define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0100 /* Disable backoff while bursting */ | ||
358 | #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0200 /* Enable hw compression -not implemented-*/ | ||
359 | |||
360 | /* | ||
361 | * A struct to hold tx queue's parameters | ||
362 | */ | ||
363 | struct ath5k_txq_info { | ||
364 | enum ath5k_tx_queue tqi_type; | ||
365 | enum ath5k_tx_queue_subtype tqi_subtype; | ||
366 | u16 tqi_flags; /* Tx queue flags (see above) */ | ||
367 | u32 tqi_aifs; /* Arbitrated Interframe Space */ | ||
368 | s32 tqi_cw_min; /* Minimum Contention Window */ | ||
369 | s32 tqi_cw_max; /* Maximum Contention Window */ | ||
370 | u32 tqi_cbr_period; /* Constant bit rate period */ | ||
371 | u32 tqi_cbr_overflow_limit; | ||
372 | u32 tqi_burst_time; | ||
373 | u32 tqi_ready_time; /* Not used */ | ||
374 | }; | ||
375 | |||
376 | /* | ||
377 | * Transmit packet types. | ||
378 | * These are not fully used inside OpenHAL yet | ||
379 | */ | ||
380 | enum ath5k_pkt_type { | ||
381 | AR5K_PKT_TYPE_NORMAL = 0, | ||
382 | AR5K_PKT_TYPE_ATIM = 1, | ||
383 | AR5K_PKT_TYPE_PSPOLL = 2, | ||
384 | AR5K_PKT_TYPE_BEACON = 3, | ||
385 | AR5K_PKT_TYPE_PROBE_RESP = 4, | ||
386 | AR5K_PKT_TYPE_PIFS = 5, | ||
387 | }; | ||
388 | |||
389 | /* | ||
390 | * TX power and TPC settings | ||
391 | */ | ||
392 | #define AR5K_TXPOWER_OFDM(_r, _v) ( \ | ||
393 | ((0 & 1) << ((_v) + 6)) | \ | ||
394 | (((ah->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v)) \ | ||
395 | ) | ||
396 | |||
397 | #define AR5K_TXPOWER_CCK(_r, _v) ( \ | ||
398 | (ah->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v) \ | ||
399 | ) | ||
400 | |||
401 | /* | ||
402 | * DMA size definitions (2^n+2) | ||
403 | */ | ||
404 | enum ath5k_dmasize { | ||
405 | AR5K_DMASIZE_4B = 0, | ||
406 | AR5K_DMASIZE_8B, | ||
407 | AR5K_DMASIZE_16B, | ||
408 | AR5K_DMASIZE_32B, | ||
409 | AR5K_DMASIZE_64B, | ||
410 | AR5K_DMASIZE_128B, | ||
411 | AR5K_DMASIZE_256B, | ||
412 | AR5K_DMASIZE_512B | ||
413 | }; | ||
414 | |||
415 | |||
416 | /****************\ | ||
417 | RX DEFINITIONS | ||
418 | \****************/ | ||
419 | |||
420 | /* | ||
421 | * Rx Descriptor | ||
422 | */ | ||
423 | struct ath5k_rx_status { | ||
424 | u16 rs_datalen; | ||
425 | u16 rs_tstamp; | ||
426 | u8 rs_status; | ||
427 | u8 rs_phyerr; | ||
428 | s8 rs_rssi; | ||
429 | u8 rs_keyix; | ||
430 | u8 rs_rate; | ||
431 | u8 rs_antenna; | ||
432 | u8 rs_more; | ||
433 | }; | ||
434 | |||
435 | #define AR5K_RXERR_CRC 0x01 | ||
436 | #define AR5K_RXERR_PHY 0x02 | ||
437 | #define AR5K_RXERR_FIFO 0x04 | ||
438 | #define AR5K_RXERR_DECRYPT 0x08 | ||
439 | #define AR5K_RXERR_MIC 0x10 | ||
440 | #define AR5K_RXKEYIX_INVALID ((u8) - 1) | ||
441 | #define AR5K_TXKEYIX_INVALID ((u32) - 1) | ||
442 | |||
443 | struct ath5k_mib_stats { | ||
444 | u32 ackrcv_bad; | ||
445 | u32 rts_bad; | ||
446 | u32 rts_good; | ||
447 | u32 fcs_bad; | ||
448 | u32 beacons; | ||
449 | }; | ||
450 | |||
451 | |||
452 | |||
453 | |||
454 | /**************************\ | ||
455 | BEACON TIMERS DEFINITIONS | ||
456 | \**************************/ | ||
457 | |||
458 | #define AR5K_BEACON_PERIOD 0x0000ffff | ||
459 | #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ | ||
460 | #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ | ||
461 | |||
462 | #if 0 | ||
463 | /** | ||
464 | * struct ath5k_beacon_state - Per-station beacon timer state. | ||
465 | * @bs_interval: in TU's, can also include the above flags | ||
466 | * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a | ||
467 | * Point Coordination Function capable AP | ||
468 | */ | ||
469 | struct ath5k_beacon_state { | ||
470 | u32 bs_next_beacon; | ||
471 | u32 bs_next_dtim; | ||
472 | u32 bs_interval; | ||
473 | u8 bs_dtim_period; | ||
474 | u8 bs_cfp_period; | ||
475 | u16 bs_cfp_max_duration; | ||
476 | u16 bs_cfp_du_remain; | ||
477 | u16 bs_tim_offset; | ||
478 | u16 bs_sleep_duration; | ||
479 | u16 bs_bmiss_threshold; | ||
480 | u32 bs_cfp_next; | ||
481 | }; | ||
482 | #endif | ||
483 | |||
484 | |||
485 | /* | ||
486 | * TSF to TU conversion: | ||
487 | * | ||
488 | * TSF is a 64bit value in usec (microseconds). | ||
489 | * TU is a 32bit value in roughly msec (milliseconds): usec / 1024 | ||
490 | * (1000ms equals 976 TU) | ||
491 | */ | ||
492 | #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) | ||
493 | |||
494 | |||
495 | |||
496 | /********************\ | ||
497 | COMMON DEFINITIONS | ||
498 | \********************/ | ||
499 | |||
500 | /* | ||
501 | * Atheros descriptor | ||
502 | */ | ||
503 | struct ath5k_desc { | ||
504 | u32 ds_link; | ||
505 | u32 ds_data; | ||
506 | u32 ds_ctl0; | ||
507 | u32 ds_ctl1; | ||
508 | u32 ds_hw[4]; | ||
509 | |||
510 | union { | ||
511 | struct ath5k_rx_status rx; | ||
512 | struct ath5k_tx_status tx; | ||
513 | } ds_us; | ||
514 | |||
515 | #define ds_rxstat ds_us.rx | ||
516 | #define ds_txstat ds_us.tx | ||
517 | |||
518 | } __packed; | ||
519 | |||
520 | #define AR5K_RXDESC_INTREQ 0x0020 | ||
521 | |||
522 | #define AR5K_TXDESC_CLRDMASK 0x0001 | ||
523 | #define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ | ||
524 | #define AR5K_TXDESC_RTSENA 0x0004 | ||
525 | #define AR5K_TXDESC_CTSENA 0x0008 | ||
526 | #define AR5K_TXDESC_INTREQ 0x0010 | ||
527 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ | ||
528 | |||
529 | #define AR5K_SLOT_TIME_9 396 | ||
530 | #define AR5K_SLOT_TIME_20 880 | ||
531 | #define AR5K_SLOT_TIME_MAX 0xffff | ||
532 | |||
533 | /* channel_flags */ | ||
534 | #define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ | ||
535 | #define CHANNEL_TURBO 0x0010 /* Turbo Channel */ | ||
536 | #define CHANNEL_CCK 0x0020 /* CCK channel */ | ||
537 | #define CHANNEL_OFDM 0x0040 /* OFDM channel */ | ||
538 | #define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ | ||
539 | #define CHANNEL_5GHZ 0x0100 /* 5GHz channel */ | ||
540 | #define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */ | ||
541 | #define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */ | ||
542 | #define CHANNEL_XR 0x0800 /* XR channel */ | ||
543 | |||
544 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | ||
545 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | ||
546 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | ||
547 | #define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) | ||
548 | #define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) | ||
549 | #define CHANNEL_108A CHANNEL_T | ||
550 | #define CHANNEL_108G CHANNEL_TG | ||
551 | #define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) | ||
552 | |||
553 | #define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ | ||
554 | CHANNEL_TURBO) | ||
555 | |||
556 | #define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) | ||
557 | #define CHANNEL_MODES CHANNEL_ALL | ||
558 | |||
559 | /* | ||
560 | * Used internaly in OpenHAL (ar5211.c/ar5212.c | ||
561 | * for reset_tx_queue). Also see struct struct ieee80211_channel. | ||
562 | */ | ||
563 | #define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0) | ||
564 | #define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0) | ||
565 | |||
566 | /* | ||
567 | * The following structure will be used to map 2GHz channels to | ||
568 | * 5GHz Atheros channels. | ||
569 | */ | ||
570 | struct ath5k_athchan_2ghz { | ||
571 | u32 a2_flags; | ||
572 | u16 a2_athchan; | ||
573 | }; | ||
574 | |||
575 | /* | ||
576 | * Rate definitions | ||
577 | * TODO: Clean them up or move them on mac80211 -most of these infos are | ||
578 | * used by the rate control algorytm on MadWiFi. | ||
579 | */ | ||
580 | |||
581 | /* Max number of rates on the rate table and what it seems | ||
582 | * Atheros hardware supports */ | ||
583 | #define AR5K_MAX_RATES 32 | ||
584 | |||
585 | /** | ||
586 | * struct ath5k_rate - rate structure | ||
587 | * @valid: is this a valid rate for the current mode | ||
588 | * @modulation: respective mac80211 modulation | ||
589 | * @rate_kbps: rate in kbit/s | ||
590 | * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on | ||
591 | * &struct ath5k_rx_status.rs_rate and on TX on | ||
592 | * &struct ath5k_tx_status.ts_rate. Seems the ar5xxx harware supports | ||
593 | * up to 32 rates, indexed by 1-32. This means we really only need | ||
594 | * 6 bits for the rate_code. | ||
595 | * @dot11_rate: respective IEEE-802.11 rate value | ||
596 | * @control_rate: index of rate assumed to be used to send control frames. | ||
597 | * This can be used to set override the value on the rate duration | ||
598 | * registers. This is only useful if we can override in the harware at | ||
599 | * what rate we want to send control frames at. Note that IEEE-802.11 | ||
600 | * Ch. 9.6 (after IEEE 802.11g changes) defines the rate at which we | ||
601 | * should send ACK/CTS, if we change this value we can be breaking | ||
602 | * the spec. | ||
603 | * | ||
604 | * This structure is used to get the RX rate or set the TX rate on the | ||
605 | * hardware descriptors. It is also used for internal modulation control | ||
606 | * and settings. | ||
607 | * | ||
608 | * On RX after the &struct ath5k_desc is parsed by the appropriate | ||
609 | * ah_proc_rx_desc() the respective hardware rate value is set in | ||
610 | * &struct ath5k_rx_status.rs_rate. On TX the desired rate is set in | ||
611 | * &struct ath5k_tx_status.ts_rate which is later used to setup the | ||
612 | * &struct ath5k_desc correctly. This is the hardware rate map we are | ||
613 | * aware of: | ||
614 | * | ||
615 | * rate_code 1 2 3 4 5 6 7 8 | ||
616 | * rate_kbps 3000 1000 ? ? ? 2000 500 48000 | ||
617 | * | ||
618 | * rate_code 9 10 11 12 13 14 15 16 | ||
619 | * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? | ||
620 | * | ||
621 | * rate_code 17 18 19 20 21 22 23 24 | ||
622 | * rate_kbps ? ? ? ? ? ? ? 11000 | ||
623 | * | ||
624 | * rate_code 25 26 27 28 29 30 31 32 | ||
625 | * rate_kbps 5500 2000 1000 ? ? ? ? ? | ||
626 | * | ||
627 | */ | ||
628 | struct ath5k_rate { | ||
629 | u8 valid; | ||
630 | u32 modulation; | ||
631 | u16 rate_kbps; | ||
632 | u8 rate_code; | ||
633 | u8 dot11_rate; | ||
634 | u8 control_rate; | ||
635 | }; | ||
636 | |||
637 | /* XXX: GRR all this stuff to get leds blinking ??? (check out setcurmode) */ | ||
638 | struct ath5k_rate_table { | ||
639 | u16 rate_count; | ||
640 | u8 rate_code_to_index[AR5K_MAX_RATES]; /* Back-mapping */ | ||
641 | struct ath5k_rate rates[AR5K_MAX_RATES]; | ||
642 | }; | ||
643 | |||
644 | /* | ||
645 | * Rate tables... | ||
646 | */ | ||
647 | #define AR5K_RATES_11A { 8, { \ | ||
648 | 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \ | ||
649 | 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
650 | 255, 255, 255, 255, 255, 255, 255, 255 }, { \ | ||
651 | { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \ | ||
652 | { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \ | ||
653 | { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \ | ||
654 | { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \ | ||
655 | { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \ | ||
656 | { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \ | ||
657 | { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \ | ||
658 | { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \ | ||
659 | } | ||
660 | |||
661 | #define AR5K_RATES_11B { 4, { \ | ||
662 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
663 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
664 | 3, 2, 1, 0, 255, 255, 255, 255 }, { \ | ||
665 | { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \ | ||
666 | { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \ | ||
667 | { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \ | ||
668 | { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \ | ||
669 | } | ||
670 | |||
671 | #define AR5K_RATES_11G { 12, { \ | ||
672 | 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \ | ||
673 | 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
674 | 3, 2, 1, 0, 255, 255, 255, 255 }, { \ | ||
675 | { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \ | ||
676 | { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \ | ||
677 | { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \ | ||
678 | { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \ | ||
679 | { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \ | ||
680 | { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \ | ||
681 | { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \ | ||
682 | { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \ | ||
683 | { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \ | ||
684 | { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \ | ||
685 | { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \ | ||
686 | { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \ | ||
687 | } | ||
688 | |||
689 | #define AR5K_RATES_TURBO { 8, { \ | ||
690 | 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \ | ||
691 | 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
692 | 255, 255, 255, 255, 255, 255, 255, 255 }, { \ | ||
693 | { 1, MODULATION_TURBO, 6000, 11, 140, 0 }, \ | ||
694 | { 1, MODULATION_TURBO, 9000, 15, 18, 0 }, \ | ||
695 | { 1, MODULATION_TURBO, 12000, 10, 152, 2 }, \ | ||
696 | { 1, MODULATION_TURBO, 18000, 14, 36, 2 }, \ | ||
697 | { 1, MODULATION_TURBO, 24000, 9, 176, 4 }, \ | ||
698 | { 1, MODULATION_TURBO, 36000, 13, 72, 4 }, \ | ||
699 | { 1, MODULATION_TURBO, 48000, 8, 96, 4 }, \ | ||
700 | { 1, MODULATION_TURBO, 54000, 12, 108, 4 } } \ | ||
701 | } | ||
702 | |||
703 | #define AR5K_RATES_XR { 12, { \ | ||
704 | 255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \ | ||
705 | 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \ | ||
706 | 255, 255, 255, 255, 255, 255, 255, 255 }, { \ | ||
707 | { 1, MODULATION_XR, 500, 7, 129, 0 }, \ | ||
708 | { 1, MODULATION_XR, 1000, 2, 139, 1 }, \ | ||
709 | { 1, MODULATION_XR, 2000, 6, 150, 2 }, \ | ||
710 | { 1, MODULATION_XR, 3000, 1, 150, 3 }, \ | ||
711 | { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \ | ||
712 | { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \ | ||
713 | { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \ | ||
714 | { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \ | ||
715 | { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \ | ||
716 | { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \ | ||
717 | { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \ | ||
718 | { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \ | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * Crypto definitions | ||
723 | */ | ||
724 | |||
725 | #define AR5K_KEYCACHE_SIZE 8 | ||
726 | |||
727 | /***********************\ | ||
728 | HW RELATED DEFINITIONS | ||
729 | \***********************/ | ||
730 | |||
731 | /* | ||
732 | * Misc definitions | ||
733 | */ | ||
734 | #define AR5K_RSSI_EP_MULTIPLIER (1<<7) | ||
735 | |||
736 | #define AR5K_ASSERT_ENTRY(_e, _s) do { \ | ||
737 | if (_e >= _s) \ | ||
738 | return (false); \ | ||
739 | } while (0) | ||
740 | |||
741 | |||
742 | enum ath5k_ant_setting { | ||
743 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ | ||
744 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ | ||
745 | AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ | ||
746 | AR5K_ANT_MAX = 3, | ||
747 | }; | ||
748 | |||
749 | /* | ||
750 | * Hardware interrupt abstraction | ||
751 | */ | ||
752 | |||
753 | /** | ||
754 | * enum ath5k_int - Hardware interrupt masks helpers | ||
755 | * | ||
756 | * @AR5K_INT_RX: mask to identify received frame interrupts, of type | ||
757 | * AR5K_ISR_RXOK or AR5K_ISR_RXERR | ||
758 | * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) | ||
759 | * @AR5K_INT_RXNOFRM: No frame received (?) | ||
760 | * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The | ||
761 | * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's | ||
762 | * LinkPtr is NULL. For more details, refer to: | ||
763 | * http://www.freepatentsonline.com/20030225739.html | ||
764 | * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). | ||
765 | * Note that Rx overrun is not always fatal, on some chips we can continue | ||
766 | * operation without reseting the card, that's why int_fatal is not | ||
767 | * common for all chips. | ||
768 | * @AR5K_INT_TX: mask to identify received frame interrupts, of type | ||
769 | * AR5K_ISR_TXOK or AR5K_ISR_TXERR | ||
770 | * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) | ||
771 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold | ||
772 | * We currently do increments on interrupt by | ||
773 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 | ||
774 | * @AR5K_INT_MIB: Indicates the Management Information Base counters should be | ||
775 | * checked. We should do this with ath5k_hw_update_mib_counters() but | ||
776 | * it seems we should also then do some noise immunity work. | ||
777 | * @AR5K_INT_RXPHY: RX PHY Error | ||
778 | * @AR5K_INT_RXKCM: ?? | ||
779 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a | ||
780 | * beacon that must be handled in software. The alternative is if you | ||
781 | * have VEOL support, in that case you let the hardware deal with things. | ||
782 | * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing | ||
783 | * beacons from the AP have associated with, we should probably try to | ||
784 | * reassociate. When in IBSS mode this might mean we have not received | ||
785 | * any beacons from any local stations. Note that every station in an | ||
786 | * IBSS schedules to send beacons at the Target Beacon Transmission Time | ||
787 | * (TBTT) with a random backoff. | ||
788 | * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? | ||
789 | * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now | ||
790 | * until properly handled | ||
791 | * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA | ||
792 | * errors. These types of errors we can enable seem to be of type | ||
793 | * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. | ||
794 | * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER | ||
795 | * @AR5K_INT_NOCARD: signals the card has been removed | ||
796 | * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same | ||
797 | * bit value | ||
798 | * | ||
799 | * These are mapped to take advantage of some common bits | ||
800 | * between the MACs, to be able to set intr properties | ||
801 | * easier. Some of them are not used yet inside hw.c. Most map | ||
802 | * to the respective hw interrupt value as they are common amogst different | ||
803 | * MACs. | ||
804 | */ | ||
805 | enum ath5k_int { | ||
806 | AR5K_INT_RX = 0x00000001, /* Not common */ | ||
807 | AR5K_INT_RXDESC = 0x00000002, | ||
808 | AR5K_INT_RXNOFRM = 0x00000008, | ||
809 | AR5K_INT_RXEOL = 0x00000010, | ||
810 | AR5K_INT_RXORN = 0x00000020, | ||
811 | AR5K_INT_TX = 0x00000040, /* Not common */ | ||
812 | AR5K_INT_TXDESC = 0x00000080, | ||
813 | AR5K_INT_TXURN = 0x00000800, | ||
814 | AR5K_INT_MIB = 0x00001000, | ||
815 | AR5K_INT_RXPHY = 0x00004000, | ||
816 | AR5K_INT_RXKCM = 0x00008000, | ||
817 | AR5K_INT_SWBA = 0x00010000, | ||
818 | AR5K_INT_BMISS = 0x00040000, | ||
819 | AR5K_INT_BNR = 0x00100000, /* Not common */ | ||
820 | AR5K_INT_GPIO = 0x01000000, | ||
821 | AR5K_INT_FATAL = 0x40000000, /* Not common */ | ||
822 | AR5K_INT_GLOBAL = 0x80000000, | ||
823 | |||
824 | AR5K_INT_COMMON = AR5K_INT_RXNOFRM | ||
825 | | AR5K_INT_RXDESC | ||
826 | | AR5K_INT_RXEOL | ||
827 | | AR5K_INT_RXORN | ||
828 | | AR5K_INT_TXURN | ||
829 | | AR5K_INT_TXDESC | ||
830 | | AR5K_INT_MIB | ||
831 | | AR5K_INT_RXPHY | ||
832 | | AR5K_INT_RXKCM | ||
833 | | AR5K_INT_SWBA | ||
834 | | AR5K_INT_BMISS | ||
835 | | AR5K_INT_GPIO, | ||
836 | AR5K_INT_NOCARD = 0xffffffff | ||
837 | }; | ||
838 | |||
839 | /* | ||
840 | * Power management | ||
841 | */ | ||
842 | enum ath5k_power_mode { | ||
843 | AR5K_PM_UNDEFINED = 0, | ||
844 | AR5K_PM_AUTO, | ||
845 | AR5K_PM_AWAKE, | ||
846 | AR5K_PM_FULL_SLEEP, | ||
847 | AR5K_PM_NETWORK_SLEEP, | ||
848 | }; | ||
849 | |||
850 | /* | ||
851 | * These match net80211 definitions (not used in | ||
852 | * d80211). | ||
853 | */ | ||
854 | #define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ | ||
855 | #define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ | ||
856 | #define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/ | ||
857 | #define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/ | ||
858 | #define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/ | ||
859 | |||
860 | /* GPIO-controlled software LED */ | ||
861 | #define AR5K_SOFTLED_PIN 0 | ||
862 | #define AR5K_SOFTLED_ON 0 | ||
863 | #define AR5K_SOFTLED_OFF 1 | ||
864 | |||
865 | /* | ||
866 | * Chipset capabilities -see ath5k_hw_get_capability- | ||
867 | * get_capability function is not yet fully implemented | ||
868 | * in OpenHAL so most of these don't work yet... | ||
869 | */ | ||
870 | enum ath5k_capability_type { | ||
871 | AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ | ||
872 | AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */ | ||
873 | AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */ | ||
874 | AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */ | ||
875 | AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */ | ||
876 | AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */ | ||
877 | AR5K_CAP_VEOL = 7, /* Supports virtual EOL */ | ||
878 | AR5K_CAP_COMPRESSION = 8, /* Supports compression */ | ||
879 | AR5K_CAP_BURST = 9, /* Supports packet bursting */ | ||
880 | AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */ | ||
881 | AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */ | ||
882 | AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */ | ||
883 | AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */ | ||
884 | AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */ | ||
885 | AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */ | ||
886 | AR5K_CAP_XR = 16, /* Supports XR mode */ | ||
887 | AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */ | ||
888 | AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */ | ||
889 | AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */ | ||
890 | AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ | ||
891 | }; | ||
892 | |||
893 | struct ath5k_capabilities { | ||
894 | /* | ||
895 | * Supported PHY modes | ||
896 | * (ie. CHANNEL_A, CHANNEL_B, ...) | ||
897 | */ | ||
898 | DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES); | ||
899 | |||
900 | /* | ||
901 | * Frequency range (without regulation restrictions) | ||
902 | */ | ||
903 | struct { | ||
904 | u16 range_2ghz_min; | ||
905 | u16 range_2ghz_max; | ||
906 | u16 range_5ghz_min; | ||
907 | u16 range_5ghz_max; | ||
908 | } cap_range; | ||
909 | |||
910 | /* | ||
911 | * Active regulation domain settings | ||
912 | */ | ||
913 | struct { | ||
914 | enum ath5k_regdom reg_current; | ||
915 | enum ath5k_regdom reg_hw; | ||
916 | } cap_regdomain; | ||
917 | |||
918 | /* | ||
919 | * Values stored in the EEPROM (some of them...) | ||
920 | */ | ||
921 | struct ath5k_eeprom_info cap_eeprom; | ||
922 | |||
923 | /* | ||
924 | * Queue information | ||
925 | */ | ||
926 | struct { | ||
927 | u8 q_tx_num; | ||
928 | } cap_queues; | ||
929 | }; | ||
930 | |||
931 | |||
932 | /***************************************\ | ||
933 | HARDWARE ABSTRACTION LAYER STRUCTURE | ||
934 | \***************************************/ | ||
935 | |||
936 | /* | ||
937 | * Misc defines | ||
938 | */ | ||
939 | |||
940 | #define AR5K_MAX_GPIO 10 | ||
941 | #define AR5K_MAX_RF_BANKS 8 | ||
942 | |||
943 | struct ath5k_hw { | ||
944 | u32 ah_magic; | ||
945 | |||
946 | struct ath5k_softc *ah_sc; | ||
947 | void __iomem *ah_iobase; | ||
948 | |||
949 | enum ath5k_int ah_imr; | ||
950 | |||
951 | enum ieee80211_if_types ah_op_mode; | ||
952 | enum ath5k_power_mode ah_power_mode; | ||
953 | struct ieee80211_channel ah_current_channel; | ||
954 | bool ah_turbo; | ||
955 | bool ah_calibration; | ||
956 | bool ah_running; | ||
957 | bool ah_single_chip; | ||
958 | enum ath5k_rfgain ah_rf_gain; | ||
959 | |||
960 | u32 ah_mac_srev; | ||
961 | u16 ah_mac_version; | ||
962 | u16 ah_mac_revision; | ||
963 | u16 ah_phy_revision; | ||
964 | u16 ah_radio_5ghz_revision; | ||
965 | u16 ah_radio_2ghz_revision; | ||
966 | |||
967 | enum ath5k_version ah_version; | ||
968 | enum ath5k_radio ah_radio; | ||
969 | u32 ah_phy; | ||
970 | |||
971 | bool ah_5ghz; | ||
972 | bool ah_2ghz; | ||
973 | |||
974 | #define ah_regdomain ah_capabilities.cap_regdomain.reg_current | ||
975 | #define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw | ||
976 | #define ah_modes ah_capabilities.cap_mode | ||
977 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version | ||
978 | |||
979 | u32 ah_atim_window; | ||
980 | u32 ah_aifs; | ||
981 | u32 ah_cw_min; | ||
982 | u32 ah_cw_max; | ||
983 | bool ah_software_retry; | ||
984 | u32 ah_limit_tx_retries; | ||
985 | |||
986 | u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | ||
987 | bool ah_ant_diversity; | ||
988 | |||
989 | u8 ah_sta_id[ETH_ALEN]; | ||
990 | |||
991 | /* Current BSSID we are trying to assoc to / creating. | ||
992 | * This is passed by mac80211 on config_interface() and cached here for | ||
993 | * use in resets */ | ||
994 | u8 ah_bssid[ETH_ALEN]; | ||
995 | |||
996 | u32 ah_gpio[AR5K_MAX_GPIO]; | ||
997 | int ah_gpio_npins; | ||
998 | |||
999 | struct ath5k_capabilities ah_capabilities; | ||
1000 | |||
1001 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; | ||
1002 | u32 ah_txq_status; | ||
1003 | u32 ah_txq_imr_txok; | ||
1004 | u32 ah_txq_imr_txerr; | ||
1005 | u32 ah_txq_imr_txurn; | ||
1006 | u32 ah_txq_imr_txdesc; | ||
1007 | u32 ah_txq_imr_txeol; | ||
1008 | u32 *ah_rf_banks; | ||
1009 | size_t ah_rf_banks_size; | ||
1010 | struct ath5k_gain ah_gain; | ||
1011 | u32 ah_offset[AR5K_MAX_RF_BANKS]; | ||
1012 | |||
1013 | struct { | ||
1014 | u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE]; | ||
1015 | u16 txp_rates[AR5K_MAX_RATES]; | ||
1016 | s16 txp_min; | ||
1017 | s16 txp_max; | ||
1018 | bool txp_tpc; | ||
1019 | s16 txp_ofdm; | ||
1020 | } ah_txpower; | ||
1021 | |||
1022 | struct { | ||
1023 | bool r_enabled; | ||
1024 | int r_last_alert; | ||
1025 | struct ieee80211_channel r_last_channel; | ||
1026 | } ah_radar; | ||
1027 | |||
1028 | /* noise floor from last periodic calibration */ | ||
1029 | s32 ah_noise_floor; | ||
1030 | |||
1031 | /* | ||
1032 | * Function pointers | ||
1033 | */ | ||
1034 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | ||
1035 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | ||
1036 | unsigned int, unsigned int, unsigned int, unsigned int, | ||
1037 | unsigned int, unsigned int, unsigned int); | ||
1038 | bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, | ||
1039 | unsigned int, unsigned int, unsigned int, unsigned int, | ||
1040 | unsigned int, unsigned int); | ||
1041 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *); | ||
1042 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *); | ||
1043 | }; | ||
1044 | |||
1045 | /* | ||
1046 | * Prototypes | ||
1047 | */ | ||
1048 | |||
1049 | /* General Functions */ | ||
1050 | extern int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set); | ||
1051 | /* Attach/Detach Functions */ | ||
1052 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); | ||
1053 | extern const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, unsigned int mode); | ||
1054 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | ||
1055 | /* Reset Functions */ | ||
1056 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel); | ||
1057 | /* Power management functions */ | ||
1058 | extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); | ||
1059 | /* DMA Related Functions */ | ||
1060 | extern void ath5k_hw_start_rx(struct ath5k_hw *ah); | ||
1061 | extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | ||
1062 | extern u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah); | ||
1063 | extern void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr); | ||
1064 | extern int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue); | ||
1065 | extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); | ||
1066 | extern u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue); | ||
1067 | extern int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr); | ||
1068 | extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | ||
1069 | /* Interrupt handling */ | ||
1070 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | ||
1071 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | ||
1072 | extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); | ||
1073 | /* EEPROM access functions */ | ||
1074 | extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); | ||
1075 | /* Protocol Control Unit Functions */ | ||
1076 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | ||
1077 | /* BSSID Functions */ | ||
1078 | extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); | ||
1079 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | ||
1080 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); | ||
1081 | extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | ||
1082 | /* Receive start/stop functions */ | ||
1083 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | ||
1084 | extern void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah); | ||
1085 | /* RX Filter functions */ | ||
1086 | extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | ||
1087 | extern int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index); | ||
1088 | extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | ||
1089 | extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | ||
1090 | extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | ||
1091 | /* Beacon related functions */ | ||
1092 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); | ||
1093 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | ||
1094 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | ||
1095 | extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | ||
1096 | #if 0 | ||
1097 | extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); | ||
1098 | extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); | ||
1099 | extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); | ||
1100 | #endif | ||
1101 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics); | ||
1102 | /* ACK bit rate */ | ||
1103 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | ||
1104 | /* ACK/CTS Timeouts */ | ||
1105 | extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1106 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | ||
1107 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1108 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | ||
1109 | /* Key table (WEP) functions */ | ||
1110 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | ||
1111 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | ||
1112 | extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); | ||
1113 | extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | ||
1114 | /* Queue Control Unit, DFS Control Unit Functions */ | ||
1115 | extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info); | ||
1116 | extern int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info); | ||
1117 | extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); | ||
1118 | extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | ||
1119 | extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | ||
1120 | extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | ||
1121 | extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | ||
1122 | extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); | ||
1123 | /* Hardware Descriptor Functions */ | ||
1124 | extern int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags); | ||
1125 | /* GPIO Functions */ | ||
1126 | extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | ||
1127 | extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); | ||
1128 | extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | ||
1129 | extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); | ||
1130 | extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | ||
1131 | extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); | ||
1132 | /* Regulatory Domain/Channels Setup */ | ||
1133 | extern u16 ath5k_get_regdomain(struct ath5k_hw *ah); | ||
1134 | /* Misc functions */ | ||
1135 | extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); | ||
1136 | |||
1137 | |||
1138 | /* Initial register settings functions */ | ||
1139 | extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | ||
1140 | /* Initialize RF */ | ||
1141 | extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode); | ||
1142 | extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq); | ||
1143 | extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah); | ||
1144 | extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah); | ||
1145 | |||
1146 | |||
1147 | /* PHY/RF channel functions */ | ||
1148 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | ||
1149 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | ||
1150 | /* PHY calibration */ | ||
1151 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | ||
1152 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | ||
1153 | /* Misc PHY functions */ | ||
1154 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | ||
1155 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); | ||
1156 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | ||
1157 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | ||
1158 | /* TX power setup */ | ||
1159 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower); | ||
1160 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power); | ||
1161 | |||
1162 | |||
1163 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | ||
1164 | { | ||
1165 | return ioread32(ah->ah_iobase + reg); | ||
1166 | } | ||
1167 | |||
1168 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | ||
1169 | { | ||
1170 | iowrite32(val, ah->ah_iobase + reg); | ||
1171 | } | ||
1172 | |||
1173 | #endif | ||
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c new file mode 100644 index 000000000000..d3d37282f3dc --- /dev/null +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -0,0 +1,2817 @@ | |||
1 | /*- | ||
2 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
3 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
4 | * Copyright (c) 2006 Devicescape Software, Inc. | ||
5 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
6 | * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer, | ||
15 | * without modification. | ||
16 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
17 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
18 | * redistribution must be conditioned upon including a substantially | ||
19 | * similar Disclaimer requirement for further binary redistribution. | ||
20 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
21 | * of any contributors may be used to endorse or promote products derived | ||
22 | * from this software without specific prior written permission. | ||
23 | * | ||
24 | * Alternatively, this software may be distributed under the terms of the | ||
25 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
26 | * Software Foundation. | ||
27 | * | ||
28 | * NO WARRANTY | ||
29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
30 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
31 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
32 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
33 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
34 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
35 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
37 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
38 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
39 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | #include <linux/version.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/delay.h> | ||
46 | #include <linux/if.h> | ||
47 | #include <linux/netdevice.h> | ||
48 | #include <linux/cache.h> | ||
49 | #include <linux/pci.h> | ||
50 | #include <linux/ethtool.h> | ||
51 | #include <linux/uaccess.h> | ||
52 | |||
53 | #include <net/ieee80211_radiotap.h> | ||
54 | |||
55 | #include <asm/unaligned.h> | ||
56 | |||
57 | #include "base.h" | ||
58 | #include "reg.h" | ||
59 | #include "debug.h" | ||
60 | |||
61 | /* unaligned little endian access */ | ||
62 | #define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p)))) | ||
63 | #define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p)))) | ||
64 | |||
65 | enum { | ||
66 | ATH_LED_TX, | ||
67 | ATH_LED_RX, | ||
68 | }; | ||
69 | |||
70 | static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | ||
71 | |||
72 | |||
73 | /******************\ | ||
74 | * Internal defines * | ||
75 | \******************/ | ||
76 | |||
77 | /* Module info */ | ||
78 | MODULE_AUTHOR("Jiri Slaby"); | ||
79 | MODULE_AUTHOR("Nick Kossifidis"); | ||
80 | MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); | ||
81 | MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); | ||
82 | MODULE_LICENSE("Dual BSD/GPL"); | ||
83 | MODULE_VERSION("0.1.1 (EXPERIMENTAL)"); | ||
84 | |||
85 | |||
86 | /* Known PCI ids */ | ||
87 | static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { | ||
88 | { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ | ||
89 | { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ | ||
90 | { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ | ||
91 | { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */ | ||
92 | { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */ | ||
93 | { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */ | ||
94 | { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */ | ||
95 | { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */ | ||
96 | { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
97 | { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
98 | { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
99 | { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
100 | { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
101 | { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ | ||
102 | { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ | ||
103 | { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ | ||
104 | { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/ | ||
105 | { PCI_VDEVICE(ATHEROS, 0x0023), .driver_data = AR5K_AR5212 }, /* 5416 */ | ||
106 | { PCI_VDEVICE(ATHEROS, 0x0024), .driver_data = AR5K_AR5212 }, /* 5418 */ | ||
107 | { 0 } | ||
108 | }; | ||
109 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | ||
110 | |||
111 | /* Known SREVs */ | ||
112 | static struct ath5k_srev_name srev_names[] = { | ||
113 | { "5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210 }, | ||
114 | { "5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311 }, | ||
115 | { "5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A }, | ||
116 | { "5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B }, | ||
117 | { "5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211 }, | ||
118 | { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 }, | ||
119 | { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 }, | ||
120 | { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A }, | ||
121 | { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 }, | ||
122 | { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 }, | ||
123 | { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 }, | ||
124 | { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, | ||
125 | { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, | ||
126 | { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, | ||
127 | { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, | ||
128 | { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, | ||
129 | { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, | ||
130 | { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, | ||
131 | { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, | ||
132 | { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, | ||
133 | { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, | ||
134 | { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, | ||
135 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 }, | ||
136 | { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 }, | ||
137 | { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, | ||
138 | { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | * Prototypes - PCI stack related functions | ||
143 | */ | ||
144 | static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | ||
145 | const struct pci_device_id *id); | ||
146 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | ||
147 | #ifdef CONFIG_PM | ||
148 | static int ath5k_pci_suspend(struct pci_dev *pdev, | ||
149 | pm_message_t state); | ||
150 | static int ath5k_pci_resume(struct pci_dev *pdev); | ||
151 | #else | ||
152 | #define ath5k_pci_suspend NULL | ||
153 | #define ath5k_pci_resume NULL | ||
154 | #endif /* CONFIG_PM */ | ||
155 | |||
156 | static struct pci_driver ath5k_pci_drv_id = { | ||
157 | .name = "ath5k_pci", | ||
158 | .id_table = ath5k_pci_id_table, | ||
159 | .probe = ath5k_pci_probe, | ||
160 | .remove = __devexit_p(ath5k_pci_remove), | ||
161 | .suspend = ath5k_pci_suspend, | ||
162 | .resume = ath5k_pci_resume, | ||
163 | }; | ||
164 | |||
165 | |||
166 | |||
167 | /* | ||
168 | * Prototypes - MAC 802.11 stack related functions | ||
169 | */ | ||
170 | static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
171 | struct ieee80211_tx_control *ctl); | ||
172 | static int ath5k_reset(struct ieee80211_hw *hw); | ||
173 | static int ath5k_start(struct ieee80211_hw *hw); | ||
174 | static void ath5k_stop(struct ieee80211_hw *hw); | ||
175 | static int ath5k_add_interface(struct ieee80211_hw *hw, | ||
176 | struct ieee80211_if_init_conf *conf); | ||
177 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | ||
178 | struct ieee80211_if_init_conf *conf); | ||
179 | static int ath5k_config(struct ieee80211_hw *hw, | ||
180 | struct ieee80211_conf *conf); | ||
181 | static int ath5k_config_interface(struct ieee80211_hw *hw, int if_id, | ||
182 | struct ieee80211_if_conf *conf); | ||
183 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | ||
184 | unsigned int changed_flags, | ||
185 | unsigned int *new_flags, | ||
186 | int mc_count, struct dev_mc_list *mclist); | ||
187 | static int ath5k_set_key(struct ieee80211_hw *hw, | ||
188 | enum set_key_cmd cmd, | ||
189 | const u8 *local_addr, const u8 *addr, | ||
190 | struct ieee80211_key_conf *key); | ||
191 | static int ath5k_get_stats(struct ieee80211_hw *hw, | ||
192 | struct ieee80211_low_level_stats *stats); | ||
193 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
194 | struct ieee80211_tx_queue_stats *stats); | ||
195 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | ||
196 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | ||
197 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | ||
198 | struct sk_buff *skb, | ||
199 | struct ieee80211_tx_control *ctl); | ||
200 | |||
201 | static struct ieee80211_ops ath5k_hw_ops = { | ||
202 | .tx = ath5k_tx, | ||
203 | .start = ath5k_start, | ||
204 | .stop = ath5k_stop, | ||
205 | .add_interface = ath5k_add_interface, | ||
206 | .remove_interface = ath5k_remove_interface, | ||
207 | .config = ath5k_config, | ||
208 | .config_interface = ath5k_config_interface, | ||
209 | .configure_filter = ath5k_configure_filter, | ||
210 | .set_key = ath5k_set_key, | ||
211 | .get_stats = ath5k_get_stats, | ||
212 | .conf_tx = NULL, | ||
213 | .get_tx_stats = ath5k_get_tx_stats, | ||
214 | .get_tsf = ath5k_get_tsf, | ||
215 | .reset_tsf = ath5k_reset_tsf, | ||
216 | .beacon_update = ath5k_beacon_update, | ||
217 | }; | ||
218 | |||
219 | /* | ||
220 | * Prototypes - Internal functions | ||
221 | */ | ||
222 | /* Attach detach */ | ||
223 | static int ath5k_attach(struct pci_dev *pdev, | ||
224 | struct ieee80211_hw *hw); | ||
225 | static void ath5k_detach(struct pci_dev *pdev, | ||
226 | struct ieee80211_hw *hw); | ||
227 | /* Channel/mode setup */ | ||
228 | static inline short ath5k_ieee2mhz(short chan); | ||
229 | static unsigned int ath5k_copy_rates(struct ieee80211_rate *rates, | ||
230 | const struct ath5k_rate_table *rt, | ||
231 | unsigned int max); | ||
232 | static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, | ||
233 | struct ieee80211_channel *channels, | ||
234 | unsigned int mode, | ||
235 | unsigned int max); | ||
236 | static int ath5k_getchannels(struct ieee80211_hw *hw); | ||
237 | static int ath5k_chan_set(struct ath5k_softc *sc, | ||
238 | struct ieee80211_channel *chan); | ||
239 | static void ath5k_setcurmode(struct ath5k_softc *sc, | ||
240 | unsigned int mode); | ||
241 | static void ath5k_mode_setup(struct ath5k_softc *sc); | ||
242 | /* Descriptor setup */ | ||
243 | static int ath5k_desc_alloc(struct ath5k_softc *sc, | ||
244 | struct pci_dev *pdev); | ||
245 | static void ath5k_desc_free(struct ath5k_softc *sc, | ||
246 | struct pci_dev *pdev); | ||
247 | /* Buffers setup */ | ||
248 | static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | ||
249 | struct ath5k_buf *bf); | ||
250 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | ||
251 | struct ath5k_buf *bf, | ||
252 | struct ieee80211_tx_control *ctl); | ||
253 | |||
254 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | ||
255 | struct ath5k_buf *bf) | ||
256 | { | ||
257 | BUG_ON(!bf); | ||
258 | if (!bf->skb) | ||
259 | return; | ||
260 | pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, | ||
261 | PCI_DMA_TODEVICE); | ||
262 | dev_kfree_skb(bf->skb); | ||
263 | bf->skb = NULL; | ||
264 | } | ||
265 | |||
266 | /* Queues setup */ | ||
267 | static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, | ||
268 | int qtype, int subtype); | ||
269 | static int ath5k_beaconq_setup(struct ath5k_hw *ah); | ||
270 | static int ath5k_beaconq_config(struct ath5k_softc *sc); | ||
271 | static void ath5k_txq_drainq(struct ath5k_softc *sc, | ||
272 | struct ath5k_txq *txq); | ||
273 | static void ath5k_txq_cleanup(struct ath5k_softc *sc); | ||
274 | static void ath5k_txq_release(struct ath5k_softc *sc); | ||
275 | /* Rx handling */ | ||
276 | static int ath5k_rx_start(struct ath5k_softc *sc); | ||
277 | static void ath5k_rx_stop(struct ath5k_softc *sc); | ||
278 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | ||
279 | struct ath5k_desc *ds, | ||
280 | struct sk_buff *skb); | ||
281 | static void ath5k_tasklet_rx(unsigned long data); | ||
282 | /* Tx handling */ | ||
283 | static void ath5k_tx_processq(struct ath5k_softc *sc, | ||
284 | struct ath5k_txq *txq); | ||
285 | static void ath5k_tasklet_tx(unsigned long data); | ||
286 | /* Beacon handling */ | ||
287 | static int ath5k_beacon_setup(struct ath5k_softc *sc, | ||
288 | struct ath5k_buf *bf, | ||
289 | struct ieee80211_tx_control *ctl); | ||
290 | static void ath5k_beacon_send(struct ath5k_softc *sc); | ||
291 | static void ath5k_beacon_config(struct ath5k_softc *sc); | ||
292 | |||
293 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | ||
294 | { | ||
295 | u64 tsf = ath5k_hw_get_tsf64(ah); | ||
296 | |||
297 | if ((tsf & 0x7fff) < rstamp) | ||
298 | tsf -= 0x8000; | ||
299 | |||
300 | return (tsf & ~0x7fff) | rstamp; | ||
301 | } | ||
302 | |||
303 | /* Interrupt handling */ | ||
304 | static int ath5k_init(struct ath5k_softc *sc); | ||
305 | static int ath5k_stop_locked(struct ath5k_softc *sc); | ||
306 | static int ath5k_stop_hw(struct ath5k_softc *sc); | ||
307 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | ||
308 | static void ath5k_tasklet_reset(unsigned long data); | ||
309 | |||
310 | static void ath5k_calibrate(unsigned long data); | ||
311 | /* LED functions */ | ||
312 | static void ath5k_led_off(unsigned long data); | ||
313 | static void ath5k_led_blink(struct ath5k_softc *sc, | ||
314 | unsigned int on, | ||
315 | unsigned int off); | ||
316 | static void ath5k_led_event(struct ath5k_softc *sc, | ||
317 | int event); | ||
318 | |||
319 | |||
320 | /* | ||
321 | * Module init/exit functions | ||
322 | */ | ||
323 | static int __init | ||
324 | init_ath5k_pci(void) | ||
325 | { | ||
326 | int ret; | ||
327 | |||
328 | ath5k_debug_init(); | ||
329 | |||
330 | ret = pci_register_driver(&ath5k_pci_drv_id); | ||
331 | if (ret) { | ||
332 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static void __exit | ||
340 | exit_ath5k_pci(void) | ||
341 | { | ||
342 | pci_unregister_driver(&ath5k_pci_drv_id); | ||
343 | |||
344 | ath5k_debug_finish(); | ||
345 | } | ||
346 | |||
347 | module_init(init_ath5k_pci); | ||
348 | module_exit(exit_ath5k_pci); | ||
349 | |||
350 | |||
351 | /********************\ | ||
352 | * PCI Initialization * | ||
353 | \********************/ | ||
354 | |||
355 | static const char * | ||
356 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | ||
357 | { | ||
358 | const char *name = "xxxxx"; | ||
359 | unsigned int i; | ||
360 | |||
361 | for (i = 0; i < ARRAY_SIZE(srev_names); i++) { | ||
362 | if (srev_names[i].sr_type != type) | ||
363 | continue; | ||
364 | if ((val & 0xff) < srev_names[i + 1].sr_val) { | ||
365 | name = srev_names[i].sr_name; | ||
366 | break; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | return name; | ||
371 | } | ||
372 | |||
373 | static int __devinit | ||
374 | ath5k_pci_probe(struct pci_dev *pdev, | ||
375 | const struct pci_device_id *id) | ||
376 | { | ||
377 | void __iomem *mem; | ||
378 | struct ath5k_softc *sc; | ||
379 | struct ieee80211_hw *hw; | ||
380 | int ret; | ||
381 | u8 csz; | ||
382 | |||
383 | ret = pci_enable_device(pdev); | ||
384 | if (ret) { | ||
385 | dev_err(&pdev->dev, "can't enable device\n"); | ||
386 | goto err; | ||
387 | } | ||
388 | |||
389 | /* XXX 32-bit addressing only */ | ||
390 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
391 | if (ret) { | ||
392 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
393 | goto err_dis; | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * Cache line size is used to size and align various | ||
398 | * structures used to communicate with the hardware. | ||
399 | */ | ||
400 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
401 | if (csz == 0) { | ||
402 | /* | ||
403 | * Linux 2.4.18 (at least) writes the cache line size | ||
404 | * register as a 16-bit wide register which is wrong. | ||
405 | * We must have this setup properly for rx buffer | ||
406 | * DMA to work so force a reasonable value here if it | ||
407 | * comes up zero. | ||
408 | */ | ||
409 | csz = L1_CACHE_BYTES / sizeof(u32); | ||
410 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
411 | } | ||
412 | /* | ||
413 | * The default setting of latency timer yields poor results, | ||
414 | * set it to the value used by other systems. It may be worth | ||
415 | * tweaking this setting more. | ||
416 | */ | ||
417 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
418 | |||
419 | /* Enable bus mastering */ | ||
420 | pci_set_master(pdev); | ||
421 | |||
422 | /* | ||
423 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
424 | * PCI Tx retries from interfering with C3 CPU state. | ||
425 | */ | ||
426 | pci_write_config_byte(pdev, 0x41, 0); | ||
427 | |||
428 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
429 | if (ret) { | ||
430 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
431 | goto err_dis; | ||
432 | } | ||
433 | |||
434 | mem = pci_iomap(pdev, 0, 0); | ||
435 | if (!mem) { | ||
436 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
437 | ret = -EIO; | ||
438 | goto err_reg; | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Allocate hw (mac80211 main struct) | ||
443 | * and hw->priv (driver private data) | ||
444 | */ | ||
445 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
446 | if (hw == NULL) { | ||
447 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
448 | ret = -ENOMEM; | ||
449 | goto err_map; | ||
450 | } | ||
451 | |||
452 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
453 | |||
454 | /* Initialize driver private data */ | ||
455 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
456 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; | ||
457 | hw->extra_tx_headroom = 2; | ||
458 | hw->channel_change_time = 5000; | ||
459 | /* these names are misleading */ | ||
460 | hw->max_rssi = -110; /* signal in dBm */ | ||
461 | hw->max_noise = -110; /* noise in dBm */ | ||
462 | hw->max_signal = 100; /* we will provide a percentage based on rssi */ | ||
463 | sc = hw->priv; | ||
464 | sc->hw = hw; | ||
465 | sc->pdev = pdev; | ||
466 | |||
467 | ath5k_debug_init_device(sc); | ||
468 | |||
469 | /* | ||
470 | * Mark the device as detached to avoid processing | ||
471 | * interrupts until setup is complete. | ||
472 | */ | ||
473 | __set_bit(ATH_STAT_INVALID, sc->status); | ||
474 | |||
475 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
476 | sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ | ||
477 | sc->opmode = IEEE80211_IF_TYPE_STA; | ||
478 | mutex_init(&sc->lock); | ||
479 | spin_lock_init(&sc->rxbuflock); | ||
480 | spin_lock_init(&sc->txbuflock); | ||
481 | |||
482 | /* Set private data */ | ||
483 | pci_set_drvdata(pdev, hw); | ||
484 | |||
485 | /* Enable msi for devices that support it */ | ||
486 | pci_enable_msi(pdev); | ||
487 | |||
488 | /* Setup interrupt handler */ | ||
489 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | ||
490 | if (ret) { | ||
491 | ATH5K_ERR(sc, "request_irq failed\n"); | ||
492 | goto err_free; | ||
493 | } | ||
494 | |||
495 | /* Initialize device */ | ||
496 | sc->ah = ath5k_hw_attach(sc, id->driver_data); | ||
497 | if (IS_ERR(sc->ah)) { | ||
498 | ret = PTR_ERR(sc->ah); | ||
499 | goto err_irq; | ||
500 | } | ||
501 | |||
502 | /* Finish private driver data initialization */ | ||
503 | ret = ath5k_attach(pdev, hw); | ||
504 | if (ret) | ||
505 | goto err_ah; | ||
506 | |||
507 | ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", | ||
508 | ath5k_chip_name(AR5K_VERSION_VER,sc->ah->ah_mac_srev), | ||
509 | sc->ah->ah_mac_srev, | ||
510 | sc->ah->ah_phy_revision); | ||
511 | |||
512 | if(!sc->ah->ah_single_chip){ | ||
513 | /* Single chip radio (!RF5111) */ | ||
514 | if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) { | ||
515 | /* No 5GHz support -> report 2GHz radio */ | ||
516 | if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){ | ||
517 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
518 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | ||
519 | sc->ah->ah_radio_5ghz_revision); | ||
520 | /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */ | ||
521 | } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){ | ||
522 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
523 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | ||
524 | sc->ah->ah_radio_5ghz_revision); | ||
525 | /* Multiband radio */ | ||
526 | } else { | ||
527 | ATH5K_INFO(sc, "RF%s multiband radio found" | ||
528 | " (0x%x)\n", | ||
529 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | ||
530 | sc->ah->ah_radio_5ghz_revision); | ||
531 | } | ||
532 | } | ||
533 | /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */ | ||
534 | else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){ | ||
535 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
536 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), | ||
537 | sc->ah->ah_radio_5ghz_revision); | ||
538 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
539 | ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision), | ||
540 | sc->ah->ah_radio_2ghz_revision); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | |||
545 | /* ready to process interrupts */ | ||
546 | __clear_bit(ATH_STAT_INVALID, sc->status); | ||
547 | |||
548 | return 0; | ||
549 | err_ah: | ||
550 | ath5k_hw_detach(sc->ah); | ||
551 | err_irq: | ||
552 | free_irq(pdev->irq, sc); | ||
553 | err_free: | ||
554 | pci_disable_msi(pdev); | ||
555 | ieee80211_free_hw(hw); | ||
556 | err_map: | ||
557 | pci_iounmap(pdev, mem); | ||
558 | err_reg: | ||
559 | pci_release_region(pdev, 0); | ||
560 | err_dis: | ||
561 | pci_disable_device(pdev); | ||
562 | err: | ||
563 | return ret; | ||
564 | } | ||
565 | |||
566 | static void __devexit | ||
567 | ath5k_pci_remove(struct pci_dev *pdev) | ||
568 | { | ||
569 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
570 | struct ath5k_softc *sc = hw->priv; | ||
571 | |||
572 | ath5k_debug_finish_device(sc); | ||
573 | ath5k_detach(pdev, hw); | ||
574 | ath5k_hw_detach(sc->ah); | ||
575 | free_irq(pdev->irq, sc); | ||
576 | pci_disable_msi(pdev); | ||
577 | pci_iounmap(pdev, sc->iobase); | ||
578 | pci_release_region(pdev, 0); | ||
579 | pci_disable_device(pdev); | ||
580 | ieee80211_free_hw(hw); | ||
581 | } | ||
582 | |||
583 | #ifdef CONFIG_PM | ||
584 | static int | ||
585 | ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
586 | { | ||
587 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
588 | struct ath5k_softc *sc = hw->priv; | ||
589 | |||
590 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) | ||
591 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1); | ||
592 | |||
593 | ath5k_stop_hw(sc); | ||
594 | pci_save_state(pdev); | ||
595 | pci_disable_device(pdev); | ||
596 | pci_set_power_state(pdev, PCI_D3hot); | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | static int | ||
602 | ath5k_pci_resume(struct pci_dev *pdev) | ||
603 | { | ||
604 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
605 | struct ath5k_softc *sc = hw->priv; | ||
606 | int err; | ||
607 | |||
608 | err = pci_set_power_state(pdev, PCI_D0); | ||
609 | if (err) | ||
610 | return err; | ||
611 | |||
612 | err = pci_enable_device(pdev); | ||
613 | if (err) | ||
614 | return err; | ||
615 | |||
616 | pci_restore_state(pdev); | ||
617 | /* | ||
618 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
619 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
620 | * PCI Tx retries from interfering with C3 CPU state | ||
621 | */ | ||
622 | pci_write_config_byte(pdev, 0x41, 0); | ||
623 | |||
624 | ath5k_init(sc); | ||
625 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
626 | ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); | ||
627 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, 0); | ||
628 | } | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | #endif /* CONFIG_PM */ | ||
633 | |||
634 | |||
635 | |||
636 | /***********************\ | ||
637 | * Driver Initialization * | ||
638 | \***********************/ | ||
639 | |||
640 | static int | ||
641 | ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
642 | { | ||
643 | struct ath5k_softc *sc = hw->priv; | ||
644 | struct ath5k_hw *ah = sc->ah; | ||
645 | u8 mac[ETH_ALEN]; | ||
646 | unsigned int i; | ||
647 | int ret; | ||
648 | |||
649 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); | ||
650 | |||
651 | /* | ||
652 | * Check if the MAC has multi-rate retry support. | ||
653 | * We do this by trying to setup a fake extended | ||
654 | * descriptor. MAC's that don't have support will | ||
655 | * return false w/o doing anything. MAC's that do | ||
656 | * support it will return true w/o doing anything. | ||
657 | */ | ||
658 | if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0)) | ||
659 | __set_bit(ATH_STAT_MRRETRY, sc->status); | ||
660 | |||
661 | /* | ||
662 | * Reset the key cache since some parts do not | ||
663 | * reset the contents on initial power up. | ||
664 | */ | ||
665 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | ||
666 | ath5k_hw_reset_key(ah, i); | ||
667 | |||
668 | /* | ||
669 | * Collect the channel list. The 802.11 layer | ||
670 | * is resposible for filtering this list based | ||
671 | * on settings like the phy mode and regulatory | ||
672 | * domain restrictions. | ||
673 | */ | ||
674 | ret = ath5k_getchannels(hw); | ||
675 | if (ret) { | ||
676 | ATH5K_ERR(sc, "can't get channels\n"); | ||
677 | goto err; | ||
678 | } | ||
679 | |||
680 | /* NB: setup here so ath5k_rate_update is happy */ | ||
681 | if (test_bit(MODE_IEEE80211A, ah->ah_modes)) | ||
682 | ath5k_setcurmode(sc, MODE_IEEE80211A); | ||
683 | else | ||
684 | ath5k_setcurmode(sc, MODE_IEEE80211B); | ||
685 | |||
686 | /* | ||
687 | * Allocate tx+rx descriptors and populate the lists. | ||
688 | */ | ||
689 | ret = ath5k_desc_alloc(sc, pdev); | ||
690 | if (ret) { | ||
691 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
692 | goto err; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * Allocate hardware transmit queues: one queue for | ||
697 | * beacon frames and one data queue for each QoS | ||
698 | * priority. Note that hw functions handle reseting | ||
699 | * these queues at the needed time. | ||
700 | */ | ||
701 | ret = ath5k_beaconq_setup(ah); | ||
702 | if (ret < 0) { | ||
703 | ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); | ||
704 | goto err_desc; | ||
705 | } | ||
706 | sc->bhalq = ret; | ||
707 | |||
708 | sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); | ||
709 | if (IS_ERR(sc->txq)) { | ||
710 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
711 | ret = PTR_ERR(sc->txq); | ||
712 | goto err_bhal; | ||
713 | } | ||
714 | |||
715 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | ||
716 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | ||
717 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | ||
718 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); | ||
719 | setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc); | ||
720 | |||
721 | sc->led_on = 0; /* low true */ | ||
722 | /* | ||
723 | * Auto-enable soft led processing for IBM cards and for | ||
724 | * 5211 minipci cards. | ||
725 | */ | ||
726 | if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || | ||
727 | pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { | ||
728 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
729 | sc->led_pin = 0; | ||
730 | } | ||
731 | /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ | ||
732 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { | ||
733 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
734 | sc->led_pin = 0; | ||
735 | } | ||
736 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
737 | ath5k_hw_set_gpio_output(ah, sc->led_pin); | ||
738 | ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); | ||
739 | } | ||
740 | |||
741 | ath5k_hw_get_lladdr(ah, mac); | ||
742 | SET_IEEE80211_PERM_ADDR(hw, mac); | ||
743 | /* All MAC address bits matter for ACKs */ | ||
744 | memset(sc->bssidmask, 0xff, ETH_ALEN); | ||
745 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
746 | |||
747 | ret = ieee80211_register_hw(hw); | ||
748 | if (ret) { | ||
749 | ATH5K_ERR(sc, "can't register ieee80211 hw\n"); | ||
750 | goto err_queues; | ||
751 | } | ||
752 | |||
753 | return 0; | ||
754 | err_queues: | ||
755 | ath5k_txq_release(sc); | ||
756 | err_bhal: | ||
757 | ath5k_hw_release_tx_queue(ah, sc->bhalq); | ||
758 | err_desc: | ||
759 | ath5k_desc_free(sc, pdev); | ||
760 | err: | ||
761 | return ret; | ||
762 | } | ||
763 | |||
764 | static void | ||
765 | ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
766 | { | ||
767 | struct ath5k_softc *sc = hw->priv; | ||
768 | |||
769 | /* | ||
770 | * NB: the order of these is important: | ||
771 | * o call the 802.11 layer before detaching ath5k_hw to | ||
772 | * insure callbacks into the driver to delete global | ||
773 | * key cache entries can be handled | ||
774 | * o reclaim the tx queue data structures after calling | ||
775 | * the 802.11 layer as we'll get called back to reclaim | ||
776 | * node state and potentially want to use them | ||
777 | * o to cleanup the tx queues the hal is called, so detach | ||
778 | * it last | ||
779 | * XXX: ??? detach ath5k_hw ??? | ||
780 | * Other than that, it's straightforward... | ||
781 | */ | ||
782 | ieee80211_unregister_hw(hw); | ||
783 | ath5k_desc_free(sc, pdev); | ||
784 | ath5k_txq_release(sc); | ||
785 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | ||
786 | |||
787 | /* | ||
788 | * NB: can't reclaim these until after ieee80211_ifdetach | ||
789 | * returns because we'll get called back to reclaim node | ||
790 | * state and potentially want to use them. | ||
791 | */ | ||
792 | } | ||
793 | |||
794 | |||
795 | |||
796 | |||
797 | /********************\ | ||
798 | * Channel/mode setup * | ||
799 | \********************/ | ||
800 | |||
801 | /* | ||
802 | * Convert IEEE channel number to MHz frequency. | ||
803 | */ | ||
804 | static inline short | ||
805 | ath5k_ieee2mhz(short chan) | ||
806 | { | ||
807 | if (chan <= 14 || chan >= 27) | ||
808 | return ieee80211chan2mhz(chan); | ||
809 | else | ||
810 | return 2212 + chan * 20; | ||
811 | } | ||
812 | |||
813 | static unsigned int | ||
814 | ath5k_copy_rates(struct ieee80211_rate *rates, | ||
815 | const struct ath5k_rate_table *rt, | ||
816 | unsigned int max) | ||
817 | { | ||
818 | unsigned int i, count; | ||
819 | |||
820 | if (rt == NULL) | ||
821 | return 0; | ||
822 | |||
823 | for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) { | ||
824 | if (!rt->rates[i].valid) | ||
825 | continue; | ||
826 | rates->rate = rt->rates[i].rate_kbps / 100; | ||
827 | rates->val = rt->rates[i].rate_code; | ||
828 | rates->flags = rt->rates[i].modulation; | ||
829 | rates++; | ||
830 | count++; | ||
831 | max--; | ||
832 | } | ||
833 | |||
834 | return count; | ||
835 | } | ||
836 | |||
837 | static unsigned int | ||
838 | ath5k_copy_channels(struct ath5k_hw *ah, | ||
839 | struct ieee80211_channel *channels, | ||
840 | unsigned int mode, | ||
841 | unsigned int max) | ||
842 | { | ||
843 | static const struct { unsigned int mode, mask, chan; } map[] = { | ||
844 | [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A }, | ||
845 | [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T }, | ||
846 | [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B }, | ||
847 | [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G }, | ||
848 | [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG }, | ||
849 | }; | ||
850 | static const struct ath5k_regchannel chans_2ghz[] = | ||
851 | IEEE80211_CHANNELS_2GHZ; | ||
852 | static const struct ath5k_regchannel chans_5ghz[] = | ||
853 | IEEE80211_CHANNELS_5GHZ; | ||
854 | const struct ath5k_regchannel *chans; | ||
855 | enum ath5k_regdom dmn; | ||
856 | unsigned int i, count, size, chfreq, all, f, ch; | ||
857 | |||
858 | if (!test_bit(mode, ah->ah_modes)) | ||
859 | return 0; | ||
860 | |||
861 | all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1; | ||
862 | |||
863 | switch (mode) { | ||
864 | case MODE_IEEE80211A: | ||
865 | case MODE_ATHEROS_TURBO: | ||
866 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ | ||
867 | size = all ? 220 : ARRAY_SIZE(chans_5ghz); | ||
868 | chans = chans_5ghz; | ||
869 | dmn = ath5k_regdom2flag(ah->ah_regdomain, | ||
870 | IEEE80211_CHANNELS_5GHZ_MIN); | ||
871 | chfreq = CHANNEL_5GHZ; | ||
872 | break; | ||
873 | case MODE_IEEE80211B: | ||
874 | case MODE_IEEE80211G: | ||
875 | case MODE_ATHEROS_TURBOG: | ||
876 | size = all ? 26 : ARRAY_SIZE(chans_2ghz); | ||
877 | chans = chans_2ghz; | ||
878 | dmn = ath5k_regdom2flag(ah->ah_regdomain, | ||
879 | IEEE80211_CHANNELS_2GHZ_MIN); | ||
880 | chfreq = CHANNEL_2GHZ; | ||
881 | break; | ||
882 | default: | ||
883 | ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | for (i = 0, count = 0; i < size && max > 0; i++) { | ||
888 | ch = all ? i + 1 : chans[i].chan; | ||
889 | f = ath5k_ieee2mhz(ch); | ||
890 | /* Check if channel is supported by the chipset */ | ||
891 | if (!ath5k_channel_ok(ah, f, chfreq)) | ||
892 | continue; | ||
893 | |||
894 | /* Match regulation domain */ | ||
895 | if (!all && !(IEEE80211_DMN(chans[i].domain) & | ||
896 | IEEE80211_DMN(dmn))) | ||
897 | continue; | ||
898 | |||
899 | if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode) | ||
900 | continue; | ||
901 | |||
902 | /* Write channel and increment counter */ | ||
903 | channels->chan = ch; | ||
904 | channels->freq = f; | ||
905 | channels->val = map[mode].chan; | ||
906 | channels++; | ||
907 | count++; | ||
908 | max--; | ||
909 | } | ||
910 | |||
911 | return count; | ||
912 | } | ||
913 | |||
914 | /* Only tries to register modes our EEPROM says it can support */ | ||
915 | #define REGISTER_MODE(m) do { \ | ||
916 | ret = ath5k_register_mode(hw, m); \ | ||
917 | if (ret) \ | ||
918 | return ret; \ | ||
919 | } while (0) \ | ||
920 | |||
921 | static inline int | ||
922 | ath5k_register_mode(struct ieee80211_hw *hw, u8 m) | ||
923 | { | ||
924 | struct ath5k_softc *sc = hw->priv; | ||
925 | struct ieee80211_hw_mode *modes = sc->modes; | ||
926 | unsigned int i; | ||
927 | int ret; | ||
928 | |||
929 | if (!test_bit(m, sc->ah->ah_capabilities.cap_mode)) | ||
930 | return 0; | ||
931 | |||
932 | for (i = 0; i < NUM_DRIVER_MODES; i++) { | ||
933 | if (modes[i].mode != m || !modes[i].num_channels) | ||
934 | continue; | ||
935 | ret = ieee80211_register_hwmode(hw, &modes[i]); | ||
936 | if (ret) { | ||
937 | ATH5K_ERR(sc, "can't register hwmode %u\n", m); | ||
938 | return ret; | ||
939 | } | ||
940 | return 0; | ||
941 | } | ||
942 | BUG(); | ||
943 | } | ||
944 | |||
945 | static int | ||
946 | ath5k_getchannels(struct ieee80211_hw *hw) | ||
947 | { | ||
948 | struct ath5k_softc *sc = hw->priv; | ||
949 | struct ath5k_hw *ah = sc->ah; | ||
950 | struct ieee80211_hw_mode *modes = sc->modes; | ||
951 | unsigned int i, max_r, max_c; | ||
952 | int ret; | ||
953 | |||
954 | BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3); | ||
955 | |||
956 | /* The order here does not matter */ | ||
957 | modes[0].mode = MODE_IEEE80211G; | ||
958 | modes[1].mode = MODE_IEEE80211B; | ||
959 | modes[2].mode = MODE_IEEE80211A; | ||
960 | |||
961 | max_r = ARRAY_SIZE(sc->rates); | ||
962 | max_c = ARRAY_SIZE(sc->channels); | ||
963 | |||
964 | for (i = 0; i < NUM_DRIVER_MODES; i++) { | ||
965 | struct ieee80211_hw_mode *mode = &modes[i]; | ||
966 | const struct ath5k_rate_table *hw_rates; | ||
967 | |||
968 | if (i == 0) { | ||
969 | modes[0].rates = sc->rates; | ||
970 | modes->channels = sc->channels; | ||
971 | } else { | ||
972 | struct ieee80211_hw_mode *prev_mode = &modes[i-1]; | ||
973 | int prev_num_r = prev_mode->num_rates; | ||
974 | int prev_num_c = prev_mode->num_channels; | ||
975 | mode->rates = &prev_mode->rates[prev_num_r]; | ||
976 | mode->channels = &prev_mode->channels[prev_num_c]; | ||
977 | } | ||
978 | |||
979 | hw_rates = ath5k_hw_get_rate_table(ah, mode->mode); | ||
980 | mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates, | ||
981 | max_r); | ||
982 | mode->num_channels = ath5k_copy_channels(ah, mode->channels, | ||
983 | mode->mode, max_c); | ||
984 | max_r -= mode->num_rates; | ||
985 | max_c -= mode->num_channels; | ||
986 | } | ||
987 | |||
988 | /* We try to register all modes this driver supports. We don't bother | ||
989 | * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts | ||
990 | * for that as per mac80211. Then, REGISTER_MODE() will will actually | ||
991 | * check the eeprom reading for more reliable capability information. | ||
992 | * Order matters here as per mac80211's latest preference. This will | ||
993 | * all hopefullly soon go away. */ | ||
994 | |||
995 | REGISTER_MODE(MODE_IEEE80211G); | ||
996 | if (ah->ah_version != AR5K_AR5212) | ||
997 | REGISTER_MODE(MODE_IEEE80211B); | ||
998 | REGISTER_MODE(MODE_IEEE80211A); | ||
999 | |||
1000 | ath5k_debug_dump_modes(sc, modes); | ||
1001 | |||
1002 | return ret; | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * Set/change channels. If the channel is really being changed, | ||
1007 | * it's done by reseting the chip. To accomplish this we must | ||
1008 | * first cleanup any pending DMA, then restart stuff after a la | ||
1009 | * ath5k_init. | ||
1010 | */ | ||
1011 | static int | ||
1012 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | ||
1013 | { | ||
1014 | struct ath5k_hw *ah = sc->ah; | ||
1015 | int ret; | ||
1016 | |||
1017 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n", | ||
1018 | sc->curchan->chan, sc->curchan->freq, | ||
1019 | chan->chan, chan->freq); | ||
1020 | |||
1021 | if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) { | ||
1022 | /* | ||
1023 | * To switch channels clear any pending DMA operations; | ||
1024 | * wait long enough for the RX fifo to drain, reset the | ||
1025 | * hardware at the new frequency, and then re-enable | ||
1026 | * the relevant bits of the h/w. | ||
1027 | */ | ||
1028 | ath5k_hw_set_intr(ah, 0); /* disable interrupts */ | ||
1029 | ath5k_txq_cleanup(sc); /* clear pending tx frames */ | ||
1030 | ath5k_rx_stop(sc); /* turn off frame recv */ | ||
1031 | ret = ath5k_hw_reset(ah, sc->opmode, chan, true); | ||
1032 | if (ret) { | ||
1033 | ATH5K_ERR(sc, "%s: unable to reset channel %u " | ||
1034 | "(%u Mhz)\n", __func__, chan->chan, chan->freq); | ||
1035 | return ret; | ||
1036 | } | ||
1037 | sc->curchan = chan; | ||
1038 | ath5k_hw_set_txpower_limit(sc->ah, 0); | ||
1039 | |||
1040 | /* | ||
1041 | * Re-enable rx framework. | ||
1042 | */ | ||
1043 | ret = ath5k_rx_start(sc); | ||
1044 | if (ret) { | ||
1045 | ATH5K_ERR(sc, "%s: unable to restart recv logic\n", | ||
1046 | __func__); | ||
1047 | return ret; | ||
1048 | } | ||
1049 | |||
1050 | /* | ||
1051 | * Change channels and update the h/w rate map | ||
1052 | * if we're switching; e.g. 11a to 11b/g. | ||
1053 | * | ||
1054 | * XXX needed? | ||
1055 | */ | ||
1056 | /* ath5k_chan_change(sc, chan); */ | ||
1057 | |||
1058 | ath5k_beacon_config(sc); | ||
1059 | /* | ||
1060 | * Re-enable interrupts. | ||
1061 | */ | ||
1062 | ath5k_hw_set_intr(ah, sc->imask); | ||
1063 | } | ||
1064 | |||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static void | ||
1069 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | ||
1070 | { | ||
1071 | if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) { | ||
1072 | /* from Atheros NDIS driver, w/ permission */ | ||
1073 | static const struct { | ||
1074 | u16 rate; /* tx/rx 802.11 rate */ | ||
1075 | u16 timeOn; /* LED on time (ms) */ | ||
1076 | u16 timeOff; /* LED off time (ms) */ | ||
1077 | } blinkrates[] = { | ||
1078 | { 108, 40, 10 }, | ||
1079 | { 96, 44, 11 }, | ||
1080 | { 72, 50, 13 }, | ||
1081 | { 48, 57, 14 }, | ||
1082 | { 36, 67, 16 }, | ||
1083 | { 24, 80, 20 }, | ||
1084 | { 22, 100, 25 }, | ||
1085 | { 18, 133, 34 }, | ||
1086 | { 12, 160, 40 }, | ||
1087 | { 10, 200, 50 }, | ||
1088 | { 6, 240, 58 }, | ||
1089 | { 4, 267, 66 }, | ||
1090 | { 2, 400, 100 }, | ||
1091 | { 0, 500, 130 } | ||
1092 | }; | ||
1093 | const struct ath5k_rate_table *rt = | ||
1094 | ath5k_hw_get_rate_table(sc->ah, mode); | ||
1095 | unsigned int i, j; | ||
1096 | |||
1097 | BUG_ON(rt == NULL); | ||
1098 | |||
1099 | memset(sc->hwmap, 0, sizeof(sc->hwmap)); | ||
1100 | for (i = 0; i < 32; i++) { | ||
1101 | u8 ix = rt->rate_code_to_index[i]; | ||
1102 | if (ix == 0xff) { | ||
1103 | sc->hwmap[i].ledon = msecs_to_jiffies(500); | ||
1104 | sc->hwmap[i].ledoff = msecs_to_jiffies(130); | ||
1105 | continue; | ||
1106 | } | ||
1107 | sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; | ||
1108 | if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation == | ||
1109 | IEEE80211_RATE_OFDM) | ||
1110 | sc->hwmap[i].txflags |= | ||
1111 | IEEE80211_RADIOTAP_F_SHORTPRE; | ||
1112 | /* receive frames include FCS */ | ||
1113 | sc->hwmap[i].rxflags = sc->hwmap[i].txflags | | ||
1114 | IEEE80211_RADIOTAP_F_FCS; | ||
1115 | /* setup blink rate table to avoid per-packet lookup */ | ||
1116 | for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++) | ||
1117 | if (blinkrates[j].rate == /* XXX why 7f? */ | ||
1118 | (rt->rates[ix].dot11_rate&0x7f)) | ||
1119 | break; | ||
1120 | |||
1121 | sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j]. | ||
1122 | timeOn); | ||
1123 | sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j]. | ||
1124 | timeOff); | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | sc->curmode = mode; | ||
1129 | } | ||
1130 | |||
1131 | static void | ||
1132 | ath5k_mode_setup(struct ath5k_softc *sc) | ||
1133 | { | ||
1134 | struct ath5k_hw *ah = sc->ah; | ||
1135 | u32 rfilt; | ||
1136 | |||
1137 | /* configure rx filter */ | ||
1138 | rfilt = sc->filter_flags; | ||
1139 | ath5k_hw_set_rx_filter(ah, rfilt); | ||
1140 | |||
1141 | if (ath5k_hw_hasbssidmask(ah)) | ||
1142 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | ||
1143 | |||
1144 | /* configure operational mode */ | ||
1145 | ath5k_hw_set_opmode(ah); | ||
1146 | |||
1147 | ath5k_hw_set_mcast_filter(ah, 0, 0); | ||
1148 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | |||
1153 | |||
1154 | /***************\ | ||
1155 | * Buffers setup * | ||
1156 | \***************/ | ||
1157 | |||
1158 | static int | ||
1159 | ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | ||
1160 | { | ||
1161 | struct ath5k_hw *ah = sc->ah; | ||
1162 | struct sk_buff *skb = bf->skb; | ||
1163 | struct ath5k_desc *ds; | ||
1164 | |||
1165 | if (likely(skb == NULL)) { | ||
1166 | unsigned int off; | ||
1167 | |||
1168 | /* | ||
1169 | * Allocate buffer with headroom_needed space for the | ||
1170 | * fake physical layer header at the start. | ||
1171 | */ | ||
1172 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | ||
1173 | if (unlikely(skb == NULL)) { | ||
1174 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | ||
1175 | sc->rxbufsize + sc->cachelsz - 1); | ||
1176 | return -ENOMEM; | ||
1177 | } | ||
1178 | /* | ||
1179 | * Cache-line-align. This is important (for the | ||
1180 | * 5210 at least) as not doing so causes bogus data | ||
1181 | * in rx'd frames. | ||
1182 | */ | ||
1183 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1184 | if (off != 0) | ||
1185 | skb_reserve(skb, sc->cachelsz - off); | ||
1186 | |||
1187 | bf->skb = skb; | ||
1188 | bf->skbaddr = pci_map_single(sc->pdev, | ||
1189 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | ||
1190 | if (unlikely(pci_dma_mapping_error(bf->skbaddr))) { | ||
1191 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | ||
1192 | dev_kfree_skb(skb); | ||
1193 | bf->skb = NULL; | ||
1194 | return -ENOMEM; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /* | ||
1199 | * Setup descriptors. For receive we always terminate | ||
1200 | * the descriptor list with a self-linked entry so we'll | ||
1201 | * not get overrun under high load (as can happen with a | ||
1202 | * 5212 when ANI processing enables PHY error frames). | ||
1203 | * | ||
1204 | * To insure the last descriptor is self-linked we create | ||
1205 | * each descriptor as self-linked and add it to the end. As | ||
1206 | * each additional descriptor is added the previous self-linked | ||
1207 | * entry is ``fixed'' naturally. This should be safe even | ||
1208 | * if DMA is happening. When processing RX interrupts we | ||
1209 | * never remove/process the last, self-linked, entry on the | ||
1210 | * descriptor list. This insures the hardware always has | ||
1211 | * someplace to write a new frame. | ||
1212 | */ | ||
1213 | ds = bf->desc; | ||
1214 | ds->ds_link = bf->daddr; /* link to self */ | ||
1215 | ds->ds_data = bf->skbaddr; | ||
1216 | ath5k_hw_setup_rx_desc(ah, ds, | ||
1217 | skb_tailroom(skb), /* buffer size */ | ||
1218 | 0); | ||
1219 | |||
1220 | if (sc->rxlink != NULL) | ||
1221 | *sc->rxlink = bf->daddr; | ||
1222 | sc->rxlink = &ds->ds_link; | ||
1223 | return 0; | ||
1224 | } | ||
1225 | |||
1226 | static int | ||
1227 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | ||
1228 | struct ieee80211_tx_control *ctl) | ||
1229 | { | ||
1230 | struct ath5k_hw *ah = sc->ah; | ||
1231 | struct ath5k_txq *txq = sc->txq; | ||
1232 | struct ath5k_desc *ds = bf->desc; | ||
1233 | struct sk_buff *skb = bf->skb; | ||
1234 | unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; | ||
1235 | int ret; | ||
1236 | |||
1237 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; | ||
1238 | bf->ctl = *ctl; | ||
1239 | /* XXX endianness */ | ||
1240 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | ||
1241 | PCI_DMA_TODEVICE); | ||
1242 | |||
1243 | if (ctl->flags & IEEE80211_TXCTL_NO_ACK) | ||
1244 | flags |= AR5K_TXDESC_NOACK; | ||
1245 | |||
1246 | pktlen = skb->len + FCS_LEN; | ||
1247 | |||
1248 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) { | ||
1249 | keyidx = ctl->key_idx; | ||
1250 | pktlen += ctl->icv_len; | ||
1251 | } | ||
1252 | |||
1253 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | ||
1254 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | ||
1255 | (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0); | ||
1256 | if (ret) | ||
1257 | goto err_unmap; | ||
1258 | |||
1259 | ds->ds_link = 0; | ||
1260 | ds->ds_data = bf->skbaddr; | ||
1261 | |||
1262 | spin_lock_bh(&txq->lock); | ||
1263 | list_add_tail(&bf->list, &txq->q); | ||
1264 | sc->tx_stats.data[txq->qnum].len++; | ||
1265 | if (txq->link == NULL) /* is this first packet? */ | ||
1266 | ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr); | ||
1267 | else /* no, so only link it */ | ||
1268 | *txq->link = bf->daddr; | ||
1269 | |||
1270 | txq->link = &ds->ds_link; | ||
1271 | ath5k_hw_tx_start(ah, txq->qnum); | ||
1272 | spin_unlock_bh(&txq->lock); | ||
1273 | |||
1274 | return 0; | ||
1275 | err_unmap: | ||
1276 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); | ||
1277 | return ret; | ||
1278 | } | ||
1279 | |||
1280 | /*******************\ | ||
1281 | * Descriptors setup * | ||
1282 | \*******************/ | ||
1283 | |||
1284 | static int | ||
1285 | ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) | ||
1286 | { | ||
1287 | struct ath5k_desc *ds; | ||
1288 | struct ath5k_buf *bf; | ||
1289 | dma_addr_t da; | ||
1290 | unsigned int i; | ||
1291 | int ret; | ||
1292 | |||
1293 | /* allocate descriptors */ | ||
1294 | sc->desc_len = sizeof(struct ath5k_desc) * | ||
1295 | (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); | ||
1296 | sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); | ||
1297 | if (sc->desc == NULL) { | ||
1298 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
1299 | ret = -ENOMEM; | ||
1300 | goto err; | ||
1301 | } | ||
1302 | ds = sc->desc; | ||
1303 | da = sc->desc_daddr; | ||
1304 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", | ||
1305 | ds, sc->desc_len, (unsigned long long)sc->desc_daddr); | ||
1306 | |||
1307 | bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF, | ||
1308 | sizeof(struct ath5k_buf), GFP_KERNEL); | ||
1309 | if (bf == NULL) { | ||
1310 | ATH5K_ERR(sc, "can't allocate bufptr\n"); | ||
1311 | ret = -ENOMEM; | ||
1312 | goto err_free; | ||
1313 | } | ||
1314 | sc->bufptr = bf; | ||
1315 | |||
1316 | INIT_LIST_HEAD(&sc->rxbuf); | ||
1317 | for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { | ||
1318 | bf->desc = ds; | ||
1319 | bf->daddr = da; | ||
1320 | list_add_tail(&bf->list, &sc->rxbuf); | ||
1321 | } | ||
1322 | |||
1323 | INIT_LIST_HEAD(&sc->txbuf); | ||
1324 | sc->txbuf_len = ATH_TXBUF; | ||
1325 | for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, | ||
1326 | da += sizeof(*ds)) { | ||
1327 | bf->desc = ds; | ||
1328 | bf->daddr = da; | ||
1329 | list_add_tail(&bf->list, &sc->txbuf); | ||
1330 | } | ||
1331 | |||
1332 | /* beacon buffer */ | ||
1333 | bf->desc = ds; | ||
1334 | bf->daddr = da; | ||
1335 | sc->bbuf = bf; | ||
1336 | |||
1337 | return 0; | ||
1338 | err_free: | ||
1339 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | ||
1340 | err: | ||
1341 | sc->desc = NULL; | ||
1342 | return ret; | ||
1343 | } | ||
1344 | |||
1345 | static void | ||
1346 | ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | ||
1347 | { | ||
1348 | struct ath5k_buf *bf; | ||
1349 | |||
1350 | ath5k_txbuf_free(sc, sc->bbuf); | ||
1351 | list_for_each_entry(bf, &sc->txbuf, list) | ||
1352 | ath5k_txbuf_free(sc, bf); | ||
1353 | list_for_each_entry(bf, &sc->rxbuf, list) | ||
1354 | ath5k_txbuf_free(sc, bf); | ||
1355 | |||
1356 | /* Free memory associated with all descriptors */ | ||
1357 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | ||
1358 | |||
1359 | kfree(sc->bufptr); | ||
1360 | sc->bufptr = NULL; | ||
1361 | } | ||
1362 | |||
1363 | |||
1364 | |||
1365 | |||
1366 | |||
1367 | /**************\ | ||
1368 | * Queues setup * | ||
1369 | \**************/ | ||
1370 | |||
1371 | static struct ath5k_txq * | ||
1372 | ath5k_txq_setup(struct ath5k_softc *sc, | ||
1373 | int qtype, int subtype) | ||
1374 | { | ||
1375 | struct ath5k_hw *ah = sc->ah; | ||
1376 | struct ath5k_txq *txq; | ||
1377 | struct ath5k_txq_info qi = { | ||
1378 | .tqi_subtype = subtype, | ||
1379 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | ||
1380 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | ||
1381 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT | ||
1382 | }; | ||
1383 | int qnum; | ||
1384 | |||
1385 | /* | ||
1386 | * Enable interrupts only for EOL and DESC conditions. | ||
1387 | * We mark tx descriptors to receive a DESC interrupt | ||
1388 | * when a tx queue gets deep; otherwise waiting for the | ||
1389 | * EOL to reap descriptors. Note that this is done to | ||
1390 | * reduce interrupt load and this only defers reaping | ||
1391 | * descriptors, never transmitting frames. Aside from | ||
1392 | * reducing interrupts this also permits more concurrency. | ||
1393 | * The only potential downside is if the tx queue backs | ||
1394 | * up in which case the top half of the kernel may backup | ||
1395 | * due to a lack of tx descriptors. | ||
1396 | */ | ||
1397 | qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE | | ||
1398 | AR5K_TXQ_FLAG_TXDESCINT_ENABLE; | ||
1399 | qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi); | ||
1400 | if (qnum < 0) { | ||
1401 | /* | ||
1402 | * NB: don't print a message, this happens | ||
1403 | * normally on parts with too few tx queues | ||
1404 | */ | ||
1405 | return ERR_PTR(qnum); | ||
1406 | } | ||
1407 | if (qnum >= ARRAY_SIZE(sc->txqs)) { | ||
1408 | ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n", | ||
1409 | qnum, ARRAY_SIZE(sc->txqs)); | ||
1410 | ath5k_hw_release_tx_queue(ah, qnum); | ||
1411 | return ERR_PTR(-EINVAL); | ||
1412 | } | ||
1413 | txq = &sc->txqs[qnum]; | ||
1414 | if (!txq->setup) { | ||
1415 | txq->qnum = qnum; | ||
1416 | txq->link = NULL; | ||
1417 | INIT_LIST_HEAD(&txq->q); | ||
1418 | spin_lock_init(&txq->lock); | ||
1419 | txq->setup = true; | ||
1420 | } | ||
1421 | return &sc->txqs[qnum]; | ||
1422 | } | ||
1423 | |||
1424 | static int | ||
1425 | ath5k_beaconq_setup(struct ath5k_hw *ah) | ||
1426 | { | ||
1427 | struct ath5k_txq_info qi = { | ||
1428 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | ||
1429 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | ||
1430 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT, | ||
1431 | /* NB: for dynamic turbo, don't enable any other interrupts */ | ||
1432 | .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE | ||
1433 | }; | ||
1434 | |||
1435 | return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi); | ||
1436 | } | ||
1437 | |||
1438 | static int | ||
1439 | ath5k_beaconq_config(struct ath5k_softc *sc) | ||
1440 | { | ||
1441 | struct ath5k_hw *ah = sc->ah; | ||
1442 | struct ath5k_txq_info qi; | ||
1443 | int ret; | ||
1444 | |||
1445 | ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); | ||
1446 | if (ret) | ||
1447 | return ret; | ||
1448 | if (sc->opmode == IEEE80211_IF_TYPE_AP || | ||
1449 | sc->opmode == IEEE80211_IF_TYPE_IBSS) { | ||
1450 | /* | ||
1451 | * Always burst out beacon and CAB traffic | ||
1452 | * (aifs = cwmin = cwmax = 0) | ||
1453 | */ | ||
1454 | qi.tqi_aifs = 0; | ||
1455 | qi.tqi_cw_min = 0; | ||
1456 | qi.tqi_cw_max = 0; | ||
1457 | } | ||
1458 | |||
1459 | ret = ath5k_hw_setup_tx_queueprops(ah, sc->bhalq, &qi); | ||
1460 | if (ret) { | ||
1461 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " | ||
1462 | "hardware queue!\n", __func__); | ||
1463 | return ret; | ||
1464 | } | ||
1465 | |||
1466 | return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; | ||
1467 | } | ||
1468 | |||
1469 | static void | ||
1470 | ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | ||
1471 | { | ||
1472 | struct ath5k_buf *bf, *bf0; | ||
1473 | |||
1474 | /* | ||
1475 | * NB: this assumes output has been stopped and | ||
1476 | * we do not need to block ath5k_tx_tasklet | ||
1477 | */ | ||
1478 | spin_lock_bh(&txq->lock); | ||
1479 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | ||
1480 | ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah, | ||
1481 | bf->desc)); | ||
1482 | |||
1483 | ath5k_txbuf_free(sc, bf); | ||
1484 | |||
1485 | spin_lock_bh(&sc->txbuflock); | ||
1486 | sc->tx_stats.data[txq->qnum].len--; | ||
1487 | list_move_tail(&bf->list, &sc->txbuf); | ||
1488 | sc->txbuf_len++; | ||
1489 | spin_unlock_bh(&sc->txbuflock); | ||
1490 | } | ||
1491 | txq->link = NULL; | ||
1492 | spin_unlock_bh(&txq->lock); | ||
1493 | } | ||
1494 | |||
1495 | /* | ||
1496 | * Drain the transmit queues and reclaim resources. | ||
1497 | */ | ||
1498 | static void | ||
1499 | ath5k_txq_cleanup(struct ath5k_softc *sc) | ||
1500 | { | ||
1501 | struct ath5k_hw *ah = sc->ah; | ||
1502 | unsigned int i; | ||
1503 | |||
1504 | /* XXX return value */ | ||
1505 | if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { | ||
1506 | /* don't touch the hardware if marked invalid */ | ||
1507 | ath5k_hw_stop_tx_dma(ah, sc->bhalq); | ||
1508 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", | ||
1509 | ath5k_hw_get_tx_buf(ah, sc->bhalq)); | ||
1510 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | ||
1511 | if (sc->txqs[i].setup) { | ||
1512 | ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); | ||
1513 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " | ||
1514 | "link %p\n", | ||
1515 | sc->txqs[i].qnum, | ||
1516 | ath5k_hw_get_tx_buf(ah, | ||
1517 | sc->txqs[i].qnum), | ||
1518 | sc->txqs[i].link); | ||
1519 | } | ||
1520 | } | ||
1521 | ieee80211_start_queues(sc->hw); /* XXX move to callers */ | ||
1522 | |||
1523 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | ||
1524 | if (sc->txqs[i].setup) | ||
1525 | ath5k_txq_drainq(sc, &sc->txqs[i]); | ||
1526 | } | ||
1527 | |||
1528 | static void | ||
1529 | ath5k_txq_release(struct ath5k_softc *sc) | ||
1530 | { | ||
1531 | struct ath5k_txq *txq = sc->txqs; | ||
1532 | unsigned int i; | ||
1533 | |||
1534 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++) | ||
1535 | if (txq->setup) { | ||
1536 | ath5k_hw_release_tx_queue(sc->ah, txq->qnum); | ||
1537 | txq->setup = false; | ||
1538 | } | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | |||
1543 | |||
1544 | /*************\ | ||
1545 | * RX Handling * | ||
1546 | \*************/ | ||
1547 | |||
1548 | /* | ||
1549 | * Enable the receive h/w following a reset. | ||
1550 | */ | ||
1551 | static int | ||
1552 | ath5k_rx_start(struct ath5k_softc *sc) | ||
1553 | { | ||
1554 | struct ath5k_hw *ah = sc->ah; | ||
1555 | struct ath5k_buf *bf; | ||
1556 | int ret; | ||
1557 | |||
1558 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); | ||
1559 | |||
1560 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | ||
1561 | sc->cachelsz, sc->rxbufsize); | ||
1562 | |||
1563 | sc->rxlink = NULL; | ||
1564 | |||
1565 | spin_lock_bh(&sc->rxbuflock); | ||
1566 | list_for_each_entry(bf, &sc->rxbuf, list) { | ||
1567 | ret = ath5k_rxbuf_setup(sc, bf); | ||
1568 | if (ret != 0) { | ||
1569 | spin_unlock_bh(&sc->rxbuflock); | ||
1570 | goto err; | ||
1571 | } | ||
1572 | } | ||
1573 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | ||
1574 | spin_unlock_bh(&sc->rxbuflock); | ||
1575 | |||
1576 | ath5k_hw_put_rx_buf(ah, bf->daddr); | ||
1577 | ath5k_hw_start_rx(ah); /* enable recv descriptors */ | ||
1578 | ath5k_mode_setup(sc); /* set filters, etc. */ | ||
1579 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | ||
1580 | |||
1581 | return 0; | ||
1582 | err: | ||
1583 | return ret; | ||
1584 | } | ||
1585 | |||
1586 | /* | ||
1587 | * Disable the receive h/w in preparation for a reset. | ||
1588 | */ | ||
1589 | static void | ||
1590 | ath5k_rx_stop(struct ath5k_softc *sc) | ||
1591 | { | ||
1592 | struct ath5k_hw *ah = sc->ah; | ||
1593 | |||
1594 | ath5k_hw_stop_pcu_recv(ah); /* disable PCU */ | ||
1595 | ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ | ||
1596 | ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ | ||
1597 | mdelay(3); /* 3ms is long enough for 1 frame */ | ||
1598 | |||
1599 | ath5k_debug_printrxbuffs(sc, ah); | ||
1600 | |||
1601 | sc->rxlink = NULL; /* just in case */ | ||
1602 | } | ||
1603 | |||
1604 | static unsigned int | ||
1605 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | ||
1606 | struct sk_buff *skb) | ||
1607 | { | ||
1608 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
1609 | unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1610 | |||
1611 | if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && | ||
1612 | ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID) | ||
1613 | return RX_FLAG_DECRYPTED; | ||
1614 | |||
1615 | /* Apparently when a default key is used to decrypt the packet | ||
1616 | the hw does not set the index used to decrypt. In such cases | ||
1617 | get the index from the packet. */ | ||
1618 | if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && | ||
1619 | !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && | ||
1620 | skb->len >= hlen + 4) { | ||
1621 | keyix = skb->data[hlen + 3] >> 6; | ||
1622 | |||
1623 | if (test_bit(keyix, sc->keymap)) | ||
1624 | return RX_FLAG_DECRYPTED; | ||
1625 | } | ||
1626 | |||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static void | ||
1631 | ath5k_tasklet_rx(unsigned long data) | ||
1632 | { | ||
1633 | struct ieee80211_rx_status rxs = {}; | ||
1634 | struct sk_buff *skb; | ||
1635 | struct ath5k_softc *sc = (void *)data; | ||
1636 | struct ath5k_buf *bf; | ||
1637 | struct ath5k_desc *ds; | ||
1638 | u16 len; | ||
1639 | u8 stat; | ||
1640 | int ret; | ||
1641 | int hdrlen; | ||
1642 | int pad; | ||
1643 | |||
1644 | spin_lock(&sc->rxbuflock); | ||
1645 | do { | ||
1646 | if (unlikely(list_empty(&sc->rxbuf))) { | ||
1647 | ATH5K_WARN(sc, "empty rx buf pool\n"); | ||
1648 | break; | ||
1649 | } | ||
1650 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | ||
1651 | BUG_ON(bf->skb == NULL); | ||
1652 | skb = bf->skb; | ||
1653 | ds = bf->desc; | ||
1654 | |||
1655 | /* TODO only one segment */ | ||
1656 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, | ||
1657 | sc->desc_len, PCI_DMA_FROMDEVICE); | ||
1658 | |||
1659 | if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ | ||
1660 | break; | ||
1661 | |||
1662 | ret = sc->ah->ah_proc_rx_desc(sc->ah, ds); | ||
1663 | if (unlikely(ret == -EINPROGRESS)) | ||
1664 | break; | ||
1665 | else if (unlikely(ret)) { | ||
1666 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | ||
1667 | return; | ||
1668 | } | ||
1669 | |||
1670 | if (unlikely(ds->ds_rxstat.rs_more)) { | ||
1671 | ATH5K_WARN(sc, "unsupported jumbo\n"); | ||
1672 | goto next; | ||
1673 | } | ||
1674 | |||
1675 | stat = ds->ds_rxstat.rs_status; | ||
1676 | if (unlikely(stat)) { | ||
1677 | if (stat & AR5K_RXERR_PHY) | ||
1678 | goto next; | ||
1679 | if (stat & AR5K_RXERR_DECRYPT) { | ||
1680 | /* | ||
1681 | * Decrypt error. If the error occurred | ||
1682 | * because there was no hardware key, then | ||
1683 | * let the frame through so the upper layers | ||
1684 | * can process it. This is necessary for 5210 | ||
1685 | * parts which have no way to setup a ``clear'' | ||
1686 | * key cache entry. | ||
1687 | * | ||
1688 | * XXX do key cache faulting | ||
1689 | */ | ||
1690 | if (ds->ds_rxstat.rs_keyix == | ||
1691 | AR5K_RXKEYIX_INVALID && | ||
1692 | !(stat & AR5K_RXERR_CRC)) | ||
1693 | goto accept; | ||
1694 | } | ||
1695 | if (stat & AR5K_RXERR_MIC) { | ||
1696 | rxs.flag |= RX_FLAG_MMIC_ERROR; | ||
1697 | goto accept; | ||
1698 | } | ||
1699 | |||
1700 | /* let crypto-error packets fall through in MNTR */ | ||
1701 | if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | ||
1702 | sc->opmode != IEEE80211_IF_TYPE_MNTR) | ||
1703 | goto next; | ||
1704 | } | ||
1705 | accept: | ||
1706 | len = ds->ds_rxstat.rs_datalen; | ||
1707 | pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len, | ||
1708 | PCI_DMA_FROMDEVICE); | ||
1709 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | ||
1710 | PCI_DMA_FROMDEVICE); | ||
1711 | bf->skb = NULL; | ||
1712 | |||
1713 | skb_put(skb, len); | ||
1714 | |||
1715 | /* | ||
1716 | * the hardware adds a padding to 4 byte boundaries between | ||
1717 | * the header and the payload data if the header length is | ||
1718 | * not multiples of 4 - remove it | ||
1719 | */ | ||
1720 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1721 | if (hdrlen & 3) { | ||
1722 | pad = hdrlen % 4; | ||
1723 | memmove(skb->data + pad, skb->data, hdrlen); | ||
1724 | skb_pull(skb, pad); | ||
1725 | } | ||
1726 | |||
1727 | if (sc->opmode == IEEE80211_IF_TYPE_MNTR) | ||
1728 | rxs.mactime = ath5k_extend_tsf(sc->ah, | ||
1729 | ds->ds_rxstat.rs_tstamp); | ||
1730 | else | ||
1731 | rxs.mactime = ds->ds_rxstat.rs_tstamp; | ||
1732 | rxs.freq = sc->curchan->freq; | ||
1733 | rxs.channel = sc->curchan->chan; | ||
1734 | rxs.phymode = sc->curmode; | ||
1735 | |||
1736 | /* | ||
1737 | * signal quality: | ||
1738 | * the names here are misleading and the usage of these | ||
1739 | * values by iwconfig makes it even worse | ||
1740 | */ | ||
1741 | /* noise floor in dBm, from the last noise calibration */ | ||
1742 | rxs.noise = sc->ah->ah_noise_floor; | ||
1743 | /* signal level in dBm */ | ||
1744 | rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi; | ||
1745 | /* | ||
1746 | * "signal" is actually displayed as Link Quality by iwconfig | ||
1747 | * we provide a percentage based on rssi (assuming max rssi 64) | ||
1748 | */ | ||
1749 | rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; | ||
1750 | |||
1751 | rxs.antenna = ds->ds_rxstat.rs_antenna; | ||
1752 | rxs.rate = ds->ds_rxstat.rs_rate; | ||
1753 | rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); | ||
1754 | |||
1755 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | ||
1756 | |||
1757 | __ieee80211_rx(sc->hw, skb, &rxs); | ||
1758 | sc->led_rxrate = ds->ds_rxstat.rs_rate; | ||
1759 | ath5k_led_event(sc, ATH_LED_RX); | ||
1760 | next: | ||
1761 | list_move_tail(&bf->list, &sc->rxbuf); | ||
1762 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | ||
1763 | spin_unlock(&sc->rxbuflock); | ||
1764 | } | ||
1765 | |||
1766 | |||
1767 | |||
1768 | |||
1769 | /*************\ | ||
1770 | * TX Handling * | ||
1771 | \*************/ | ||
1772 | |||
1773 | static void | ||
1774 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | ||
1775 | { | ||
1776 | struct ieee80211_tx_status txs = {}; | ||
1777 | struct ath5k_buf *bf, *bf0; | ||
1778 | struct ath5k_desc *ds; | ||
1779 | struct sk_buff *skb; | ||
1780 | int ret; | ||
1781 | |||
1782 | spin_lock(&txq->lock); | ||
1783 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | ||
1784 | ds = bf->desc; | ||
1785 | |||
1786 | /* TODO only one segment */ | ||
1787 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, | ||
1788 | sc->desc_len, PCI_DMA_FROMDEVICE); | ||
1789 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds); | ||
1790 | if (unlikely(ret == -EINPROGRESS)) | ||
1791 | break; | ||
1792 | else if (unlikely(ret)) { | ||
1793 | ATH5K_ERR(sc, "error %d while processing queue %u\n", | ||
1794 | ret, txq->qnum); | ||
1795 | break; | ||
1796 | } | ||
1797 | |||
1798 | skb = bf->skb; | ||
1799 | bf->skb = NULL; | ||
1800 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, | ||
1801 | PCI_DMA_TODEVICE); | ||
1802 | |||
1803 | txs.control = bf->ctl; | ||
1804 | txs.retry_count = ds->ds_txstat.ts_shortretry + | ||
1805 | ds->ds_txstat.ts_longretry / 6; | ||
1806 | if (unlikely(ds->ds_txstat.ts_status)) { | ||
1807 | sc->ll_stats.dot11ACKFailureCount++; | ||
1808 | if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY) | ||
1809 | txs.excessive_retries = 1; | ||
1810 | else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT) | ||
1811 | txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED; | ||
1812 | } else { | ||
1813 | txs.flags |= IEEE80211_TX_STATUS_ACK; | ||
1814 | txs.ack_signal = ds->ds_txstat.ts_rssi; | ||
1815 | } | ||
1816 | |||
1817 | ieee80211_tx_status(sc->hw, skb, &txs); | ||
1818 | sc->tx_stats.data[txq->qnum].count++; | ||
1819 | |||
1820 | spin_lock(&sc->txbuflock); | ||
1821 | sc->tx_stats.data[txq->qnum].len--; | ||
1822 | list_move_tail(&bf->list, &sc->txbuf); | ||
1823 | sc->txbuf_len++; | ||
1824 | spin_unlock(&sc->txbuflock); | ||
1825 | } | ||
1826 | if (likely(list_empty(&txq->q))) | ||
1827 | txq->link = NULL; | ||
1828 | spin_unlock(&txq->lock); | ||
1829 | if (sc->txbuf_len > ATH_TXBUF / 5) | ||
1830 | ieee80211_wake_queues(sc->hw); | ||
1831 | } | ||
1832 | |||
1833 | static void | ||
1834 | ath5k_tasklet_tx(unsigned long data) | ||
1835 | { | ||
1836 | struct ath5k_softc *sc = (void *)data; | ||
1837 | |||
1838 | ath5k_tx_processq(sc, sc->txq); | ||
1839 | |||
1840 | ath5k_led_event(sc, ATH_LED_TX); | ||
1841 | } | ||
1842 | |||
1843 | |||
1844 | |||
1845 | |||
1846 | /*****************\ | ||
1847 | * Beacon handling * | ||
1848 | \*****************/ | ||
1849 | |||
1850 | /* | ||
1851 | * Setup the beacon frame for transmit. | ||
1852 | */ | ||
1853 | static int | ||
1854 | ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | ||
1855 | struct ieee80211_tx_control *ctl) | ||
1856 | { | ||
1857 | struct sk_buff *skb = bf->skb; | ||
1858 | struct ath5k_hw *ah = sc->ah; | ||
1859 | struct ath5k_desc *ds; | ||
1860 | int ret, antenna = 0; | ||
1861 | u32 flags; | ||
1862 | |||
1863 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | ||
1864 | PCI_DMA_TODEVICE); | ||
1865 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " | ||
1866 | "skbaddr %llx\n", skb, skb->data, skb->len, | ||
1867 | (unsigned long long)bf->skbaddr); | ||
1868 | if (pci_dma_mapping_error(bf->skbaddr)) { | ||
1869 | ATH5K_ERR(sc, "beacon DMA mapping failed\n"); | ||
1870 | return -EIO; | ||
1871 | } | ||
1872 | |||
1873 | ds = bf->desc; | ||
1874 | |||
1875 | flags = AR5K_TXDESC_NOACK; | ||
1876 | if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) { | ||
1877 | ds->ds_link = bf->daddr; /* self-linked */ | ||
1878 | flags |= AR5K_TXDESC_VEOL; | ||
1879 | /* | ||
1880 | * Let hardware handle antenna switching if txantenna is not set | ||
1881 | */ | ||
1882 | } else { | ||
1883 | ds->ds_link = 0; | ||
1884 | /* | ||
1885 | * Switch antenna every 4 beacons if txantenna is not set | ||
1886 | * XXX assumes two antennas | ||
1887 | */ | ||
1888 | if (antenna == 0) | ||
1889 | antenna = sc->bsent & 4 ? 2 : 1; | ||
1890 | } | ||
1891 | |||
1892 | ds->ds_data = bf->skbaddr; | ||
1893 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN, | ||
1894 | ieee80211_get_hdrlen_from_skb(skb), | ||
1895 | AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1, | ||
1896 | AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); | ||
1897 | if (ret) | ||
1898 | goto err_unmap; | ||
1899 | |||
1900 | return 0; | ||
1901 | err_unmap: | ||
1902 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); | ||
1903 | return ret; | ||
1904 | } | ||
1905 | |||
1906 | /* | ||
1907 | * Transmit a beacon frame at SWBA. Dynamic updates to the | ||
1908 | * frame contents are done as needed and the slot time is | ||
1909 | * also adjusted based on current state. | ||
1910 | * | ||
1911 | * this is usually called from interrupt context (ath5k_intr()) | ||
1912 | * but also from ath5k_beacon_config() in IBSS mode which in turn | ||
1913 | * can be called from a tasklet and user context | ||
1914 | */ | ||
1915 | static void | ||
1916 | ath5k_beacon_send(struct ath5k_softc *sc) | ||
1917 | { | ||
1918 | struct ath5k_buf *bf = sc->bbuf; | ||
1919 | struct ath5k_hw *ah = sc->ah; | ||
1920 | |||
1921 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n"); | ||
1922 | |||
1923 | if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA || | ||
1924 | sc->opmode == IEEE80211_IF_TYPE_MNTR)) { | ||
1925 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | ||
1926 | return; | ||
1927 | } | ||
1928 | /* | ||
1929 | * Check if the previous beacon has gone out. If | ||
1930 | * not don't don't try to post another, skip this | ||
1931 | * period and wait for the next. Missed beacons | ||
1932 | * indicate a problem and should not occur. If we | ||
1933 | * miss too many consecutive beacons reset the device. | ||
1934 | */ | ||
1935 | if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { | ||
1936 | sc->bmisscount++; | ||
1937 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, | ||
1938 | "missed %u consecutive beacons\n", sc->bmisscount); | ||
1939 | if (sc->bmisscount > 3) { /* NB: 3 is a guess */ | ||
1940 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, | ||
1941 | "stuck beacon time (%u missed)\n", | ||
1942 | sc->bmisscount); | ||
1943 | tasklet_schedule(&sc->restq); | ||
1944 | } | ||
1945 | return; | ||
1946 | } | ||
1947 | if (unlikely(sc->bmisscount != 0)) { | ||
1948 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, | ||
1949 | "resume beacon xmit after %u misses\n", | ||
1950 | sc->bmisscount); | ||
1951 | sc->bmisscount = 0; | ||
1952 | } | ||
1953 | |||
1954 | /* | ||
1955 | * Stop any current dma and put the new frame on the queue. | ||
1956 | * This should never fail since we check above that no frames | ||
1957 | * are still pending on the queue. | ||
1958 | */ | ||
1959 | if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { | ||
1960 | ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); | ||
1961 | /* NB: hw still stops DMA, so proceed */ | ||
1962 | } | ||
1963 | pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len, | ||
1964 | PCI_DMA_TODEVICE); | ||
1965 | |||
1966 | ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr); | ||
1967 | ath5k_hw_tx_start(ah, sc->bhalq); | ||
1968 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n", | ||
1969 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); | ||
1970 | |||
1971 | sc->bsent++; | ||
1972 | } | ||
1973 | |||
1974 | |||
1975 | static void | ||
1976 | ath5k_beacon_update_timers(struct ath5k_softc *sc) | ||
1977 | { | ||
1978 | struct ath5k_hw *ah = sc->ah; | ||
1979 | u32 uninitialized_var(nexttbtt), intval, tsftu; | ||
1980 | u64 tsf; | ||
1981 | |||
1982 | intval = sc->bintval & AR5K_BEACON_PERIOD; | ||
1983 | if (WARN_ON(!intval)) | ||
1984 | return; | ||
1985 | |||
1986 | /* current TSF converted to TU */ | ||
1987 | tsf = ath5k_hw_get_tsf64(ah); | ||
1988 | tsftu = TSF_TO_TU(tsf); | ||
1989 | |||
1990 | /* | ||
1991 | * Pull nexttbtt forward to reflect the current | ||
1992 | * TSF. Add one intval otherwise the timespan | ||
1993 | * can be too short for ibss merges. | ||
1994 | */ | ||
1995 | nexttbtt = tsftu + 2 * intval; | ||
1996 | |||
1997 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | ||
1998 | "hw tsftu %u nexttbtt %u intval %u\n", tsftu, nexttbtt, intval); | ||
1999 | |||
2000 | intval |= AR5K_BEACON_ENA; | ||
2001 | |||
2002 | ath5k_hw_init_beacon(ah, nexttbtt, intval); | ||
2003 | } | ||
2004 | |||
2005 | |||
2006 | /* | ||
2007 | * Configure the beacon timers and interrupts based on the operating mode | ||
2008 | * | ||
2009 | * When operating in station mode we want to receive a BMISS interrupt when we | ||
2010 | * stop seeing beacons from the AP we've associated with so we can look for | ||
2011 | * another AP to associate with. | ||
2012 | * | ||
2013 | * In IBSS mode we need to configure the beacon timers and use a self-linked tx | ||
2014 | * descriptor if possible. If the hardware cannot deal with that we enable SWBA | ||
2015 | * interrupts to send the beacons from the interrupt handler. | ||
2016 | */ | ||
2017 | static void | ||
2018 | ath5k_beacon_config(struct ath5k_softc *sc) | ||
2019 | { | ||
2020 | struct ath5k_hw *ah = sc->ah; | ||
2021 | |||
2022 | ath5k_hw_set_intr(ah, 0); | ||
2023 | sc->bmisscount = 0; | ||
2024 | |||
2025 | if (sc->opmode == IEEE80211_IF_TYPE_STA) { | ||
2026 | sc->imask |= AR5K_INT_BMISS; | ||
2027 | } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { | ||
2028 | /* | ||
2029 | * In IBSS mode enable the beacon timers but only enable SWBA | ||
2030 | * interrupts if we need to manually prepare beacon frames. | ||
2031 | * Otherwise we use a self-linked tx descriptor and let the | ||
2032 | * hardware deal with things. In that case we have to load it | ||
2033 | * only once here. | ||
2034 | */ | ||
2035 | ath5k_beaconq_config(sc); | ||
2036 | ath5k_beacon_update_timers(sc); | ||
2037 | |||
2038 | if (!ath5k_hw_hasveol(ah)) | ||
2039 | sc->imask |= AR5K_INT_SWBA; | ||
2040 | else | ||
2041 | ath5k_beacon_send(sc); | ||
2042 | } | ||
2043 | /* TODO else AP */ | ||
2044 | |||
2045 | ath5k_hw_set_intr(ah, sc->imask); | ||
2046 | } | ||
2047 | |||
2048 | |||
2049 | /********************\ | ||
2050 | * Interrupt handling * | ||
2051 | \********************/ | ||
2052 | |||
2053 | static int | ||
2054 | ath5k_init(struct ath5k_softc *sc) | ||
2055 | { | ||
2056 | int ret; | ||
2057 | |||
2058 | mutex_lock(&sc->lock); | ||
2059 | |||
2060 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | ||
2061 | |||
2062 | /* | ||
2063 | * Stop anything previously setup. This is safe | ||
2064 | * no matter this is the first time through or not. | ||
2065 | */ | ||
2066 | ath5k_stop_locked(sc); | ||
2067 | |||
2068 | /* | ||
2069 | * The basic interface to setting the hardware in a good | ||
2070 | * state is ``reset''. On return the hardware is known to | ||
2071 | * be powered up and with interrupts disabled. This must | ||
2072 | * be followed by initialization of the appropriate bits | ||
2073 | * and then setup of the interrupt mask. | ||
2074 | */ | ||
2075 | sc->curchan = sc->hw->conf.chan; | ||
2076 | ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false); | ||
2077 | if (ret) { | ||
2078 | ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret); | ||
2079 | goto done; | ||
2080 | } | ||
2081 | /* | ||
2082 | * This is needed only to setup initial state | ||
2083 | * but it's best done after a reset. | ||
2084 | */ | ||
2085 | ath5k_hw_set_txpower_limit(sc->ah, 0); | ||
2086 | |||
2087 | /* | ||
2088 | * Setup the hardware after reset: the key cache | ||
2089 | * is filled as needed and the receive engine is | ||
2090 | * set going. Frame transmit is handled entirely | ||
2091 | * in the frame output path; there's nothing to do | ||
2092 | * here except setup the interrupt mask. | ||
2093 | */ | ||
2094 | ret = ath5k_rx_start(sc); | ||
2095 | if (ret) | ||
2096 | goto done; | ||
2097 | |||
2098 | /* | ||
2099 | * Enable interrupts. | ||
2100 | */ | ||
2101 | sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | | ||
2102 | AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL; | ||
2103 | |||
2104 | ath5k_hw_set_intr(sc->ah, sc->imask); | ||
2105 | /* Set ack to be sent at low bit-rates */ | ||
2106 | ath5k_hw_set_ack_bitrate_high(sc->ah, false); | ||
2107 | |||
2108 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | ||
2109 | msecs_to_jiffies(ath5k_calinterval * 1000))); | ||
2110 | |||
2111 | ret = 0; | ||
2112 | done: | ||
2113 | mutex_unlock(&sc->lock); | ||
2114 | return ret; | ||
2115 | } | ||
2116 | |||
2117 | static int | ||
2118 | ath5k_stop_locked(struct ath5k_softc *sc) | ||
2119 | { | ||
2120 | struct ath5k_hw *ah = sc->ah; | ||
2121 | |||
2122 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", | ||
2123 | test_bit(ATH_STAT_INVALID, sc->status)); | ||
2124 | |||
2125 | /* | ||
2126 | * Shutdown the hardware and driver: | ||
2127 | * stop output from above | ||
2128 | * disable interrupts | ||
2129 | * turn off timers | ||
2130 | * turn off the radio | ||
2131 | * clear transmit machinery | ||
2132 | * clear receive machinery | ||
2133 | * drain and release tx queues | ||
2134 | * reclaim beacon resources | ||
2135 | * power down hardware | ||
2136 | * | ||
2137 | * Note that some of this work is not possible if the | ||
2138 | * hardware is gone (invalid). | ||
2139 | */ | ||
2140 | ieee80211_stop_queues(sc->hw); | ||
2141 | |||
2142 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2143 | if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { | ||
2144 | del_timer_sync(&sc->led_tim); | ||
2145 | ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); | ||
2146 | __clear_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2147 | } | ||
2148 | ath5k_hw_set_intr(ah, 0); | ||
2149 | } | ||
2150 | ath5k_txq_cleanup(sc); | ||
2151 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2152 | ath5k_rx_stop(sc); | ||
2153 | ath5k_hw_phy_disable(ah); | ||
2154 | } else | ||
2155 | sc->rxlink = NULL; | ||
2156 | |||
2157 | return 0; | ||
2158 | } | ||
2159 | |||
2160 | /* | ||
2161 | * Stop the device, grabbing the top-level lock to protect | ||
2162 | * against concurrent entry through ath5k_init (which can happen | ||
2163 | * if another thread does a system call and the thread doing the | ||
2164 | * stop is preempted). | ||
2165 | */ | ||
2166 | static int | ||
2167 | ath5k_stop_hw(struct ath5k_softc *sc) | ||
2168 | { | ||
2169 | int ret; | ||
2170 | |||
2171 | mutex_lock(&sc->lock); | ||
2172 | ret = ath5k_stop_locked(sc); | ||
2173 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2174 | /* | ||
2175 | * Set the chip in full sleep mode. Note that we are | ||
2176 | * careful to do this only when bringing the interface | ||
2177 | * completely to a stop. When the chip is in this state | ||
2178 | * it must be carefully woken up or references to | ||
2179 | * registers in the PCI clock domain may freeze the bus | ||
2180 | * (and system). This varies by chip and is mostly an | ||
2181 | * issue with newer parts that go to sleep more quickly. | ||
2182 | */ | ||
2183 | if (sc->ah->ah_mac_srev >= 0x78) { | ||
2184 | /* | ||
2185 | * XXX | ||
2186 | * don't put newer MAC revisions > 7.8 to sleep because | ||
2187 | * of the above mentioned problems | ||
2188 | */ | ||
2189 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " | ||
2190 | "not putting device to sleep\n"); | ||
2191 | } else { | ||
2192 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2193 | "putting device to full sleep\n"); | ||
2194 | ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); | ||
2195 | } | ||
2196 | } | ||
2197 | ath5k_txbuf_free(sc, sc->bbuf); | ||
2198 | mutex_unlock(&sc->lock); | ||
2199 | |||
2200 | del_timer_sync(&sc->calib_tim); | ||
2201 | |||
2202 | return ret; | ||
2203 | } | ||
2204 | |||
2205 | static irqreturn_t | ||
2206 | ath5k_intr(int irq, void *dev_id) | ||
2207 | { | ||
2208 | struct ath5k_softc *sc = dev_id; | ||
2209 | struct ath5k_hw *ah = sc->ah; | ||
2210 | enum ath5k_int status; | ||
2211 | unsigned int counter = 1000; | ||
2212 | |||
2213 | if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || | ||
2214 | !ath5k_hw_is_intr_pending(ah))) | ||
2215 | return IRQ_NONE; | ||
2216 | |||
2217 | do { | ||
2218 | /* | ||
2219 | * Figure out the reason(s) for the interrupt. Note | ||
2220 | * that get_isr returns a pseudo-ISR that may include | ||
2221 | * bits we haven't explicitly enabled so we mask the | ||
2222 | * value to insure we only process bits we requested. | ||
2223 | */ | ||
2224 | ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ | ||
2225 | ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", | ||
2226 | status, sc->imask); | ||
2227 | status &= sc->imask; /* discard unasked for bits */ | ||
2228 | if (unlikely(status & AR5K_INT_FATAL)) { | ||
2229 | /* | ||
2230 | * Fatal errors are unrecoverable. | ||
2231 | * Typically these are caused by DMA errors. | ||
2232 | */ | ||
2233 | tasklet_schedule(&sc->restq); | ||
2234 | } else if (unlikely(status & AR5K_INT_RXORN)) { | ||
2235 | tasklet_schedule(&sc->restq); | ||
2236 | } else { | ||
2237 | if (status & AR5K_INT_SWBA) { | ||
2238 | /* | ||
2239 | * Software beacon alert--time to send a beacon. | ||
2240 | * Handle beacon transmission directly; deferring | ||
2241 | * this is too slow to meet timing constraints | ||
2242 | * under load. | ||
2243 | */ | ||
2244 | ath5k_beacon_send(sc); | ||
2245 | } | ||
2246 | if (status & AR5K_INT_RXEOL) { | ||
2247 | /* | ||
2248 | * NB: the hardware should re-read the link when | ||
2249 | * RXE bit is written, but it doesn't work at | ||
2250 | * least on older hardware revs. | ||
2251 | */ | ||
2252 | sc->rxlink = NULL; | ||
2253 | } | ||
2254 | if (status & AR5K_INT_TXURN) { | ||
2255 | /* bump tx trigger level */ | ||
2256 | ath5k_hw_update_tx_triglevel(ah, true); | ||
2257 | } | ||
2258 | if (status & AR5K_INT_RX) | ||
2259 | tasklet_schedule(&sc->rxtq); | ||
2260 | if (status & AR5K_INT_TX) | ||
2261 | tasklet_schedule(&sc->txtq); | ||
2262 | if (status & AR5K_INT_BMISS) { | ||
2263 | } | ||
2264 | if (status & AR5K_INT_MIB) { | ||
2265 | /* TODO */ | ||
2266 | } | ||
2267 | } | ||
2268 | } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); | ||
2269 | |||
2270 | if (unlikely(!counter)) | ||
2271 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | ||
2272 | |||
2273 | return IRQ_HANDLED; | ||
2274 | } | ||
2275 | |||
2276 | static void | ||
2277 | ath5k_tasklet_reset(unsigned long data) | ||
2278 | { | ||
2279 | struct ath5k_softc *sc = (void *)data; | ||
2280 | |||
2281 | ath5k_reset(sc->hw); | ||
2282 | } | ||
2283 | |||
2284 | /* | ||
2285 | * Periodically recalibrate the PHY to account | ||
2286 | * for temperature/environment changes. | ||
2287 | */ | ||
2288 | static void | ||
2289 | ath5k_calibrate(unsigned long data) | ||
2290 | { | ||
2291 | struct ath5k_softc *sc = (void *)data; | ||
2292 | struct ath5k_hw *ah = sc->ah; | ||
2293 | |||
2294 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", | ||
2295 | sc->curchan->chan, sc->curchan->val); | ||
2296 | |||
2297 | if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) { | ||
2298 | /* | ||
2299 | * Rfgain is out of bounds, reset the chip | ||
2300 | * to load new gain values. | ||
2301 | */ | ||
2302 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); | ||
2303 | ath5k_reset(sc->hw); | ||
2304 | } | ||
2305 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) | ||
2306 | ATH5K_ERR(sc, "calibration of channel %u failed\n", | ||
2307 | sc->curchan->chan); | ||
2308 | |||
2309 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | ||
2310 | msecs_to_jiffies(ath5k_calinterval * 1000))); | ||
2311 | } | ||
2312 | |||
2313 | |||
2314 | |||
2315 | /***************\ | ||
2316 | * LED functions * | ||
2317 | \***************/ | ||
2318 | |||
2319 | static void | ||
2320 | ath5k_led_off(unsigned long data) | ||
2321 | { | ||
2322 | struct ath5k_softc *sc = (void *)data; | ||
2323 | |||
2324 | if (test_bit(ATH_STAT_LEDENDBLINK, sc->status)) | ||
2325 | __clear_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2326 | else { | ||
2327 | __set_bit(ATH_STAT_LEDENDBLINK, sc->status); | ||
2328 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); | ||
2329 | mod_timer(&sc->led_tim, jiffies + sc->led_off); | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | /* | ||
2334 | * Blink the LED according to the specified on/off times. | ||
2335 | */ | ||
2336 | static void | ||
2337 | ath5k_led_blink(struct ath5k_softc *sc, unsigned int on, | ||
2338 | unsigned int off) | ||
2339 | { | ||
2340 | ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off); | ||
2341 | ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); | ||
2342 | __set_bit(ATH_STAT_LEDBLINKING, sc->status); | ||
2343 | __clear_bit(ATH_STAT_LEDENDBLINK, sc->status); | ||
2344 | sc->led_off = off; | ||
2345 | mod_timer(&sc->led_tim, jiffies + on); | ||
2346 | } | ||
2347 | |||
2348 | static void | ||
2349 | ath5k_led_event(struct ath5k_softc *sc, int event) | ||
2350 | { | ||
2351 | if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status))) | ||
2352 | return; | ||
2353 | if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status))) | ||
2354 | return; /* don't interrupt active blink */ | ||
2355 | switch (event) { | ||
2356 | case ATH_LED_TX: | ||
2357 | ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon, | ||
2358 | sc->hwmap[sc->led_txrate].ledoff); | ||
2359 | break; | ||
2360 | case ATH_LED_RX: | ||
2361 | ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon, | ||
2362 | sc->hwmap[sc->led_rxrate].ledoff); | ||
2363 | break; | ||
2364 | } | ||
2365 | } | ||
2366 | |||
2367 | |||
2368 | |||
2369 | |||
2370 | /********************\ | ||
2371 | * Mac80211 functions * | ||
2372 | \********************/ | ||
2373 | |||
2374 | static int | ||
2375 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
2376 | struct ieee80211_tx_control *ctl) | ||
2377 | { | ||
2378 | struct ath5k_softc *sc = hw->priv; | ||
2379 | struct ath5k_buf *bf; | ||
2380 | unsigned long flags; | ||
2381 | int hdrlen; | ||
2382 | int pad; | ||
2383 | |||
2384 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | ||
2385 | |||
2386 | if (sc->opmode == IEEE80211_IF_TYPE_MNTR) | ||
2387 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); | ||
2388 | |||
2389 | /* | ||
2390 | * the hardware expects the header padded to 4 byte boundaries | ||
2391 | * if this is not the case we add the padding after the header | ||
2392 | */ | ||
2393 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
2394 | if (hdrlen & 3) { | ||
2395 | pad = hdrlen % 4; | ||
2396 | if (skb_headroom(skb) < pad) { | ||
2397 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | ||
2398 | " headroom to pad %d\n", hdrlen, pad); | ||
2399 | return -1; | ||
2400 | } | ||
2401 | skb_push(skb, pad); | ||
2402 | memmove(skb->data, skb->data+pad, hdrlen); | ||
2403 | } | ||
2404 | |||
2405 | sc->led_txrate = ctl->tx_rate; | ||
2406 | |||
2407 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
2408 | if (list_empty(&sc->txbuf)) { | ||
2409 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | ||
2410 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2411 | ieee80211_stop_queue(hw, ctl->queue); | ||
2412 | return -1; | ||
2413 | } | ||
2414 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | ||
2415 | list_del(&bf->list); | ||
2416 | sc->txbuf_len--; | ||
2417 | if (list_empty(&sc->txbuf)) | ||
2418 | ieee80211_stop_queues(hw); | ||
2419 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2420 | |||
2421 | bf->skb = skb; | ||
2422 | |||
2423 | if (ath5k_txbuf_setup(sc, bf, ctl)) { | ||
2424 | bf->skb = NULL; | ||
2425 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
2426 | list_add_tail(&bf->list, &sc->txbuf); | ||
2427 | sc->txbuf_len++; | ||
2428 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2429 | dev_kfree_skb_any(skb); | ||
2430 | return 0; | ||
2431 | } | ||
2432 | |||
2433 | return 0; | ||
2434 | } | ||
2435 | |||
2436 | static int | ||
2437 | ath5k_reset(struct ieee80211_hw *hw) | ||
2438 | { | ||
2439 | struct ath5k_softc *sc = hw->priv; | ||
2440 | struct ath5k_hw *ah = sc->ah; | ||
2441 | int ret; | ||
2442 | |||
2443 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); | ||
2444 | /* | ||
2445 | * Convert to a hw channel description with the flags | ||
2446 | * constrained to reflect the current operating mode. | ||
2447 | */ | ||
2448 | sc->curchan = hw->conf.chan; | ||
2449 | |||
2450 | ath5k_hw_set_intr(ah, 0); | ||
2451 | ath5k_txq_cleanup(sc); | ||
2452 | ath5k_rx_stop(sc); | ||
2453 | |||
2454 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); | ||
2455 | if (unlikely(ret)) { | ||
2456 | ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); | ||
2457 | goto err; | ||
2458 | } | ||
2459 | ath5k_hw_set_txpower_limit(sc->ah, 0); | ||
2460 | |||
2461 | ret = ath5k_rx_start(sc); | ||
2462 | if (unlikely(ret)) { | ||
2463 | ATH5K_ERR(sc, "can't start recv logic\n"); | ||
2464 | goto err; | ||
2465 | } | ||
2466 | /* | ||
2467 | * We may be doing a reset in response to an ioctl | ||
2468 | * that changes the channel so update any state that | ||
2469 | * might change as a result. | ||
2470 | * | ||
2471 | * XXX needed? | ||
2472 | */ | ||
2473 | /* ath5k_chan_change(sc, c); */ | ||
2474 | ath5k_beacon_config(sc); | ||
2475 | /* intrs are started by ath5k_beacon_config */ | ||
2476 | |||
2477 | ieee80211_wake_queues(hw); | ||
2478 | |||
2479 | return 0; | ||
2480 | err: | ||
2481 | return ret; | ||
2482 | } | ||
2483 | |||
2484 | static int ath5k_start(struct ieee80211_hw *hw) | ||
2485 | { | ||
2486 | return ath5k_init(hw->priv); | ||
2487 | } | ||
2488 | |||
2489 | static void ath5k_stop(struct ieee80211_hw *hw) | ||
2490 | { | ||
2491 | ath5k_stop_hw(hw->priv); | ||
2492 | } | ||
2493 | |||
2494 | static int ath5k_add_interface(struct ieee80211_hw *hw, | ||
2495 | struct ieee80211_if_init_conf *conf) | ||
2496 | { | ||
2497 | struct ath5k_softc *sc = hw->priv; | ||
2498 | int ret; | ||
2499 | |||
2500 | mutex_lock(&sc->lock); | ||
2501 | if (sc->iface_id) { | ||
2502 | ret = 0; | ||
2503 | goto end; | ||
2504 | } | ||
2505 | |||
2506 | sc->iface_id = conf->if_id; | ||
2507 | |||
2508 | switch (conf->type) { | ||
2509 | case IEEE80211_IF_TYPE_STA: | ||
2510 | case IEEE80211_IF_TYPE_IBSS: | ||
2511 | case IEEE80211_IF_TYPE_MNTR: | ||
2512 | sc->opmode = conf->type; | ||
2513 | break; | ||
2514 | default: | ||
2515 | ret = -EOPNOTSUPP; | ||
2516 | goto end; | ||
2517 | } | ||
2518 | ret = 0; | ||
2519 | end: | ||
2520 | mutex_unlock(&sc->lock); | ||
2521 | return ret; | ||
2522 | } | ||
2523 | |||
2524 | static void | ||
2525 | ath5k_remove_interface(struct ieee80211_hw *hw, | ||
2526 | struct ieee80211_if_init_conf *conf) | ||
2527 | { | ||
2528 | struct ath5k_softc *sc = hw->priv; | ||
2529 | |||
2530 | mutex_lock(&sc->lock); | ||
2531 | if (sc->iface_id != conf->if_id) | ||
2532 | goto end; | ||
2533 | |||
2534 | sc->iface_id = 0; | ||
2535 | end: | ||
2536 | mutex_unlock(&sc->lock); | ||
2537 | } | ||
2538 | |||
2539 | static int | ||
2540 | ath5k_config(struct ieee80211_hw *hw, | ||
2541 | struct ieee80211_conf *conf) | ||
2542 | { | ||
2543 | struct ath5k_softc *sc = hw->priv; | ||
2544 | |||
2545 | sc->bintval = conf->beacon_int * 1000 / 1024; | ||
2546 | ath5k_setcurmode(sc, conf->phymode); | ||
2547 | |||
2548 | return ath5k_chan_set(sc, conf->chan); | ||
2549 | } | ||
2550 | |||
2551 | static int | ||
2552 | ath5k_config_interface(struct ieee80211_hw *hw, int if_id, | ||
2553 | struct ieee80211_if_conf *conf) | ||
2554 | { | ||
2555 | struct ath5k_softc *sc = hw->priv; | ||
2556 | struct ath5k_hw *ah = sc->ah; | ||
2557 | int ret; | ||
2558 | |||
2559 | /* Set to a reasonable value. Note that this will | ||
2560 | * be set to mac80211's value at ath5k_config(). */ | ||
2561 | sc->bintval = 1000 * 1000 / 1024; | ||
2562 | mutex_lock(&sc->lock); | ||
2563 | if (sc->iface_id != if_id) { | ||
2564 | ret = -EIO; | ||
2565 | goto unlock; | ||
2566 | } | ||
2567 | if (conf->bssid) { | ||
2568 | /* Cache for later use during resets */ | ||
2569 | memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); | ||
2570 | /* XXX: assoc id is set to 0 for now, mac80211 doesn't have | ||
2571 | * a clean way of letting us retrieve this yet. */ | ||
2572 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
2573 | } | ||
2574 | mutex_unlock(&sc->lock); | ||
2575 | |||
2576 | return ath5k_reset(hw); | ||
2577 | unlock: | ||
2578 | mutex_unlock(&sc->lock); | ||
2579 | return ret; | ||
2580 | } | ||
2581 | |||
2582 | #define SUPPORTED_FIF_FLAGS \ | ||
2583 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | ||
2584 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | ||
2585 | FIF_BCN_PRBRESP_PROMISC | ||
2586 | /* | ||
2587 | * o always accept unicast, broadcast, and multicast traffic | ||
2588 | * o multicast traffic for all BSSIDs will be enabled if mac80211 | ||
2589 | * says it should be | ||
2590 | * o maintain current state of phy ofdm or phy cck error reception. | ||
2591 | * If the hardware detects any of these type of errors then | ||
2592 | * ath5k_hw_get_rx_filter() will pass to us the respective | ||
2593 | * hardware filters to be able to receive these type of frames. | ||
2594 | * o probe request frames are accepted only when operating in | ||
2595 | * hostap, adhoc, or monitor modes | ||
2596 | * o enable promiscuous mode according to the interface state | ||
2597 | * o accept beacons: | ||
2598 | * - when operating in adhoc mode so the 802.11 layer creates | ||
2599 | * node table entries for peers, | ||
2600 | * - when operating in station mode for collecting rssi data when | ||
2601 | * the station is otherwise quiet, or | ||
2602 | * - when scanning | ||
2603 | */ | ||
2604 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | ||
2605 | unsigned int changed_flags, | ||
2606 | unsigned int *new_flags, | ||
2607 | int mc_count, struct dev_mc_list *mclist) | ||
2608 | { | ||
2609 | struct ath5k_softc *sc = hw->priv; | ||
2610 | struct ath5k_hw *ah = sc->ah; | ||
2611 | u32 mfilt[2], val, rfilt; | ||
2612 | u8 pos; | ||
2613 | int i; | ||
2614 | |||
2615 | mfilt[0] = 0; | ||
2616 | mfilt[1] = 0; | ||
2617 | |||
2618 | /* Only deal with supported flags */ | ||
2619 | changed_flags &= SUPPORTED_FIF_FLAGS; | ||
2620 | *new_flags &= SUPPORTED_FIF_FLAGS; | ||
2621 | |||
2622 | /* If HW detects any phy or radar errors, leave those filters on. | ||
2623 | * Also, always enable Unicast, Broadcasts and Multicast | ||
2624 | * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ | ||
2625 | rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | | ||
2626 | (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | | ||
2627 | AR5K_RX_FILTER_MCAST); | ||
2628 | |||
2629 | if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | ||
2630 | if (*new_flags & FIF_PROMISC_IN_BSS) { | ||
2631 | rfilt |= AR5K_RX_FILTER_PROM; | ||
2632 | __set_bit(ATH_STAT_PROMISC, sc->status); | ||
2633 | } | ||
2634 | else | ||
2635 | __clear_bit(ATH_STAT_PROMISC, sc->status); | ||
2636 | } | ||
2637 | |||
2638 | /* Note, AR5K_RX_FILTER_MCAST is already enabled */ | ||
2639 | if (*new_flags & FIF_ALLMULTI) { | ||
2640 | mfilt[0] = ~0; | ||
2641 | mfilt[1] = ~0; | ||
2642 | } else { | ||
2643 | for (i = 0; i < mc_count; i++) { | ||
2644 | if (!mclist) | ||
2645 | break; | ||
2646 | /* calculate XOR of eight 6-bit values */ | ||
2647 | val = LE_READ_4(mclist->dmi_addr + 0); | ||
2648 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2649 | val = LE_READ_4(mclist->dmi_addr + 3); | ||
2650 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2651 | pos &= 0x3f; | ||
2652 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
2653 | /* XXX: we might be able to just do this instead, | ||
2654 | * but not sure, needs testing, if we do use this we'd | ||
2655 | * neet to inform below to not reset the mcast */ | ||
2656 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
2657 | * mclist->dmi_addr[5]); */ | ||
2658 | mclist = mclist->next; | ||
2659 | } | ||
2660 | } | ||
2661 | |||
2662 | /* This is the best we can do */ | ||
2663 | if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) | ||
2664 | rfilt |= AR5K_RX_FILTER_PHYERR; | ||
2665 | |||
2666 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | ||
2667 | * and probes for any BSSID, this needs testing */ | ||
2668 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) | ||
2669 | rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; | ||
2670 | |||
2671 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | ||
2672 | * set we should only pass on control frames for this | ||
2673 | * station. This needs testing. I believe right now this | ||
2674 | * enables *all* control frames, which is OK.. but | ||
2675 | * but we should see if we can improve on granularity */ | ||
2676 | if (*new_flags & FIF_CONTROL) | ||
2677 | rfilt |= AR5K_RX_FILTER_CONTROL; | ||
2678 | |||
2679 | /* Additional settings per mode -- this is per ath5k */ | ||
2680 | |||
2681 | /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ | ||
2682 | |||
2683 | if (sc->opmode == IEEE80211_IF_TYPE_MNTR) | ||
2684 | rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | | ||
2685 | AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; | ||
2686 | if (sc->opmode != IEEE80211_IF_TYPE_STA) | ||
2687 | rfilt |= AR5K_RX_FILTER_PROBEREQ; | ||
2688 | if (sc->opmode != IEEE80211_IF_TYPE_AP && | ||
2689 | test_bit(ATH_STAT_PROMISC, sc->status)) | ||
2690 | rfilt |= AR5K_RX_FILTER_PROM; | ||
2691 | if (sc->opmode == IEEE80211_IF_TYPE_STA || | ||
2692 | sc->opmode == IEEE80211_IF_TYPE_IBSS) { | ||
2693 | rfilt |= AR5K_RX_FILTER_BEACON; | ||
2694 | } | ||
2695 | |||
2696 | /* Set filters */ | ||
2697 | ath5k_hw_set_rx_filter(ah,rfilt); | ||
2698 | |||
2699 | /* Set multicast bits */ | ||
2700 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); | ||
2701 | /* Set the cached hw filter flags, this will alter actually | ||
2702 | * be set in HW */ | ||
2703 | sc->filter_flags = rfilt; | ||
2704 | } | ||
2705 | |||
2706 | static int | ||
2707 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
2708 | const u8 *local_addr, const u8 *addr, | ||
2709 | struct ieee80211_key_conf *key) | ||
2710 | { | ||
2711 | struct ath5k_softc *sc = hw->priv; | ||
2712 | int ret = 0; | ||
2713 | |||
2714 | switch(key->alg) { | ||
2715 | case ALG_WEP: | ||
2716 | break; | ||
2717 | case ALG_TKIP: | ||
2718 | case ALG_CCMP: | ||
2719 | return -EOPNOTSUPP; | ||
2720 | default: | ||
2721 | WARN_ON(1); | ||
2722 | return -EINVAL; | ||
2723 | } | ||
2724 | |||
2725 | mutex_lock(&sc->lock); | ||
2726 | |||
2727 | switch (cmd) { | ||
2728 | case SET_KEY: | ||
2729 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); | ||
2730 | if (ret) { | ||
2731 | ATH5K_ERR(sc, "can't set the key\n"); | ||
2732 | goto unlock; | ||
2733 | } | ||
2734 | __set_bit(key->keyidx, sc->keymap); | ||
2735 | key->hw_key_idx = key->keyidx; | ||
2736 | break; | ||
2737 | case DISABLE_KEY: | ||
2738 | ath5k_hw_reset_key(sc->ah, key->keyidx); | ||
2739 | __clear_bit(key->keyidx, sc->keymap); | ||
2740 | break; | ||
2741 | default: | ||
2742 | ret = -EINVAL; | ||
2743 | goto unlock; | ||
2744 | } | ||
2745 | |||
2746 | unlock: | ||
2747 | mutex_unlock(&sc->lock); | ||
2748 | return ret; | ||
2749 | } | ||
2750 | |||
2751 | static int | ||
2752 | ath5k_get_stats(struct ieee80211_hw *hw, | ||
2753 | struct ieee80211_low_level_stats *stats) | ||
2754 | { | ||
2755 | struct ath5k_softc *sc = hw->priv; | ||
2756 | |||
2757 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | ||
2758 | |||
2759 | return 0; | ||
2760 | } | ||
2761 | |||
2762 | static int | ||
2763 | ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
2764 | struct ieee80211_tx_queue_stats *stats) | ||
2765 | { | ||
2766 | struct ath5k_softc *sc = hw->priv; | ||
2767 | |||
2768 | memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); | ||
2769 | |||
2770 | return 0; | ||
2771 | } | ||
2772 | |||
2773 | static u64 | ||
2774 | ath5k_get_tsf(struct ieee80211_hw *hw) | ||
2775 | { | ||
2776 | struct ath5k_softc *sc = hw->priv; | ||
2777 | |||
2778 | return ath5k_hw_get_tsf64(sc->ah); | ||
2779 | } | ||
2780 | |||
2781 | static void | ||
2782 | ath5k_reset_tsf(struct ieee80211_hw *hw) | ||
2783 | { | ||
2784 | struct ath5k_softc *sc = hw->priv; | ||
2785 | |||
2786 | ath5k_hw_reset_tsf(sc->ah); | ||
2787 | } | ||
2788 | |||
2789 | static int | ||
2790 | ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
2791 | struct ieee80211_tx_control *ctl) | ||
2792 | { | ||
2793 | struct ath5k_softc *sc = hw->priv; | ||
2794 | int ret; | ||
2795 | |||
2796 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | ||
2797 | |||
2798 | mutex_lock(&sc->lock); | ||
2799 | |||
2800 | if (sc->opmode != IEEE80211_IF_TYPE_IBSS) { | ||
2801 | ret = -EIO; | ||
2802 | goto end; | ||
2803 | } | ||
2804 | |||
2805 | ath5k_txbuf_free(sc, sc->bbuf); | ||
2806 | sc->bbuf->skb = skb; | ||
2807 | ret = ath5k_beacon_setup(sc, sc->bbuf, ctl); | ||
2808 | if (ret) | ||
2809 | sc->bbuf->skb = NULL; | ||
2810 | else | ||
2811 | ath5k_beacon_config(sc); | ||
2812 | |||
2813 | end: | ||
2814 | mutex_unlock(&sc->lock); | ||
2815 | return ret; | ||
2816 | } | ||
2817 | |||
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h new file mode 100644 index 000000000000..927d67db3dc2 --- /dev/null +++ b/drivers/net/wireless/ath5k/base.h | |||
@@ -0,0 +1,178 @@ | |||
1 | /*- | ||
2 | * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * 1. Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer, | ||
10 | * without modification. | ||
11 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
12 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
13 | * redistribution must be conditioned upon including a substantially | ||
14 | * similar Disclaimer requirement for further binary redistribution. | ||
15 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
16 | * of any contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * Alternatively, this software may be distributed under the terms of the | ||
20 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
21 | * Software Foundation. | ||
22 | * | ||
23 | * NO WARRANTY | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
25 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
26 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
27 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
28 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
29 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
32 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
34 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
35 | * | ||
36 | */ | ||
37 | |||
38 | /* | ||
39 | * Defintions for the Atheros Wireless LAN controller driver. | ||
40 | */ | ||
41 | #ifndef _DEV_ATH_ATHVAR_H | ||
42 | #define _DEV_ATH_ATHVAR_H | ||
43 | |||
44 | #include <linux/interrupt.h> | ||
45 | #include <linux/list.h> | ||
46 | #include <linux/wireless.h> | ||
47 | #include <linux/if_ether.h> | ||
48 | |||
49 | #include "ath5k.h" | ||
50 | #include "debug.h" | ||
51 | |||
52 | #define ATH_RXBUF 40 /* number of RX buffers */ | ||
53 | #define ATH_TXBUF 200 /* number of TX buffers */ | ||
54 | #define ATH_BCBUF 1 /* number of beacon buffers */ | ||
55 | |||
56 | struct ath5k_buf { | ||
57 | struct list_head list; | ||
58 | unsigned int flags; /* tx descriptor flags */ | ||
59 | struct ath5k_desc *desc; /* virtual addr of desc */ | ||
60 | dma_addr_t daddr; /* physical addr of desc */ | ||
61 | struct sk_buff *skb; /* skbuff for buf */ | ||
62 | dma_addr_t skbaddr;/* physical addr of skb data */ | ||
63 | struct ieee80211_tx_control ctl; | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * Data transmit queue state. One of these exists for each | ||
68 | * hardware transmit queue. Packets sent to us from above | ||
69 | * are assigned to queues based on their priority. Not all | ||
70 | * devices support a complete set of hardware transmit queues. | ||
71 | * For those devices the array sc_ac2q will map multiple | ||
72 | * priorities to fewer hardware queues (typically all to one | ||
73 | * hardware queue). | ||
74 | */ | ||
75 | struct ath5k_txq { | ||
76 | unsigned int qnum; /* hardware q number */ | ||
77 | u32 *link; /* link ptr in last TX desc */ | ||
78 | struct list_head q; /* transmit queue */ | ||
79 | spinlock_t lock; /* lock on q and link */ | ||
80 | bool setup; | ||
81 | }; | ||
82 | |||
83 | #if CHAN_DEBUG | ||
84 | #define ATH_CHAN_MAX (26+26+26+200+200) | ||
85 | #else | ||
86 | #define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */ | ||
87 | #endif | ||
88 | |||
89 | /* Software Carrier, keeps track of the driver state | ||
90 | * associated with an instance of a device */ | ||
91 | struct ath5k_softc { | ||
92 | struct pci_dev *pdev; /* for dma mapping */ | ||
93 | void __iomem *iobase; /* address of the device */ | ||
94 | struct mutex lock; /* dev-level lock */ | ||
95 | struct ieee80211_tx_queue_stats tx_stats; | ||
96 | struct ieee80211_low_level_stats ll_stats; | ||
97 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | ||
98 | struct ieee80211_hw_mode modes[NUM_DRIVER_MODES]; | ||
99 | struct ieee80211_channel channels[ATH_CHAN_MAX]; | ||
100 | struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES]; | ||
101 | enum ieee80211_if_types opmode; | ||
102 | struct ath5k_hw *ah; /* Atheros HW */ | ||
103 | |||
104 | #if ATH5K_DEBUG | ||
105 | struct ath5k_dbg_info debug; /* debug info */ | ||
106 | #endif | ||
107 | |||
108 | struct ath5k_buf *bufptr; /* allocated buffer ptr */ | ||
109 | struct ath5k_desc *desc; /* TX/RX descriptors */ | ||
110 | dma_addr_t desc_daddr; /* DMA (physical) address */ | ||
111 | size_t desc_len; /* size of TX/RX descriptors */ | ||
112 | u16 cachelsz; /* cache line size */ | ||
113 | |||
114 | DECLARE_BITMAP(status, 6); | ||
115 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ | ||
116 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ | ||
117 | #define ATH_STAT_PROMISC 2 | ||
118 | #define ATH_STAT_LEDBLINKING 3 /* LED blink operation active */ | ||
119 | #define ATH_STAT_LEDENDBLINK 4 /* finish LED blink operation */ | ||
120 | #define ATH_STAT_LEDSOFT 5 /* enable LED gpio status */ | ||
121 | |||
122 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | ||
123 | unsigned int curmode; /* current phy mode */ | ||
124 | struct ieee80211_channel *curchan; /* current h/w channel */ | ||
125 | |||
126 | int iface_id; /* add/remove_interface id */ | ||
127 | |||
128 | struct { | ||
129 | u8 rxflags; /* radiotap rx flags */ | ||
130 | u8 txflags; /* radiotap tx flags */ | ||
131 | u16 ledon; /* softled on time */ | ||
132 | u16 ledoff; /* softled off time */ | ||
133 | } hwmap[32]; /* h/w rate ix mappings */ | ||
134 | |||
135 | enum ath5k_int imask; /* interrupt mask copy */ | ||
136 | |||
137 | DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ | ||
138 | |||
139 | u8 bssidmask[ETH_ALEN]; | ||
140 | |||
141 | unsigned int led_pin, /* GPIO pin for driving LED */ | ||
142 | led_on, /* pin setting for LED on */ | ||
143 | led_off; /* off time for current blink */ | ||
144 | struct timer_list led_tim; /* led off timer */ | ||
145 | u8 led_rxrate; /* current rx rate for LED */ | ||
146 | u8 led_txrate; /* current tx rate for LED */ | ||
147 | |||
148 | struct tasklet_struct restq; /* reset tasklet */ | ||
149 | |||
150 | unsigned int rxbufsize; /* rx size based on mtu */ | ||
151 | struct list_head rxbuf; /* receive buffer */ | ||
152 | spinlock_t rxbuflock; | ||
153 | u32 *rxlink; /* link ptr in last RX desc */ | ||
154 | struct tasklet_struct rxtq; /* rx intr tasklet */ | ||
155 | |||
156 | struct list_head txbuf; /* transmit buffer */ | ||
157 | spinlock_t txbuflock; | ||
158 | unsigned int txbuf_len; /* buf count in txbuf list */ | ||
159 | struct ath5k_txq txqs[2]; /* beacon and tx */ | ||
160 | |||
161 | struct ath5k_txq *txq; /* beacon and tx*/ | ||
162 | struct tasklet_struct txtq; /* tx intr tasklet */ | ||
163 | |||
164 | struct ath5k_buf *bbuf; /* beacon buffer */ | ||
165 | unsigned int bhalq, /* SW q for outgoing beacons */ | ||
166 | bmisscount, /* missed beacon transmits */ | ||
167 | bintval, /* beacon interval */ | ||
168 | bsent; | ||
169 | |||
170 | struct timer_list calib_tim; /* calibration timer */ | ||
171 | }; | ||
172 | |||
173 | #define ath5k_hw_hasbssidmask(_ah) \ | ||
174 | (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) | ||
175 | #define ath5k_hw_hasveol(_ah) \ | ||
176 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) | ||
177 | |||
178 | #endif | ||
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c new file mode 100644 index 000000000000..4ba649e20269 --- /dev/null +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> | ||
3 | * | ||
4 | * This file is free software: you may copy, redistribute and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation, either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This file is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * | ||
18 | * This file incorporates work covered by the following copyright and | ||
19 | * permission notice: | ||
20 | * | ||
21 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
22 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
23 | * Copyright (c) 2006 Devicescape Software, Inc. | ||
24 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
25 | * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | ||
26 | * | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * 1. Redistributions of source code must retain the above copyright | ||
33 | * notice, this list of conditions and the following disclaimer, | ||
34 | * without modification. | ||
35 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
36 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
37 | * redistribution must be conditioned upon including a substantially | ||
38 | * similar Disclaimer requirement for further binary redistribution. | ||
39 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
40 | * of any contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * Alternatively, this software may be distributed under the terms of the | ||
44 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
45 | * Software Foundation. | ||
46 | * | ||
47 | * NO WARRANTY | ||
48 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
49 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
50 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
51 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
52 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
53 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
56 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
58 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
59 | */ | ||
60 | |||
61 | #include "debug.h" | ||
62 | #include "base.h" | ||
63 | |||
64 | static unsigned int ath5k_debug; | ||
65 | module_param_named(debug, ath5k_debug, uint, 0); | ||
66 | |||
67 | |||
68 | #if ATH5K_DEBUG | ||
69 | |||
70 | #include <linux/seq_file.h> | ||
71 | #include "reg.h" | ||
72 | |||
73 | static struct dentry *ath5k_global_debugfs; | ||
74 | |||
75 | static int ath5k_debugfs_open(struct inode *inode, struct file *file) | ||
76 | { | ||
77 | file->private_data = inode->i_private; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | |||
82 | /* debugfs: registers */ | ||
83 | |||
84 | struct reg { | ||
85 | char *name; | ||
86 | int addr; | ||
87 | }; | ||
88 | |||
89 | #define REG_STRUCT_INIT(r) { #r, r } | ||
90 | |||
91 | /* just a few random registers, might want to add more */ | ||
92 | static struct reg regs[] = { | ||
93 | REG_STRUCT_INIT(AR5K_CR), | ||
94 | REG_STRUCT_INIT(AR5K_RXDP), | ||
95 | REG_STRUCT_INIT(AR5K_CFG), | ||
96 | REG_STRUCT_INIT(AR5K_IER), | ||
97 | REG_STRUCT_INIT(AR5K_BCR), | ||
98 | REG_STRUCT_INIT(AR5K_RTSD0), | ||
99 | REG_STRUCT_INIT(AR5K_RTSD1), | ||
100 | REG_STRUCT_INIT(AR5K_TXCFG), | ||
101 | REG_STRUCT_INIT(AR5K_RXCFG), | ||
102 | REG_STRUCT_INIT(AR5K_RXJLA), | ||
103 | REG_STRUCT_INIT(AR5K_MIBC), | ||
104 | REG_STRUCT_INIT(AR5K_TOPS), | ||
105 | REG_STRUCT_INIT(AR5K_RXNOFRM), | ||
106 | REG_STRUCT_INIT(AR5K_TXNOFRM), | ||
107 | REG_STRUCT_INIT(AR5K_RPGTO), | ||
108 | REG_STRUCT_INIT(AR5K_RFCNT), | ||
109 | REG_STRUCT_INIT(AR5K_MISC), | ||
110 | REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), | ||
111 | REG_STRUCT_INIT(AR5K_ISR), | ||
112 | REG_STRUCT_INIT(AR5K_PISR), | ||
113 | REG_STRUCT_INIT(AR5K_SISR0), | ||
114 | REG_STRUCT_INIT(AR5K_SISR1), | ||
115 | REG_STRUCT_INIT(AR5K_SISR2), | ||
116 | REG_STRUCT_INIT(AR5K_SISR3), | ||
117 | REG_STRUCT_INIT(AR5K_SISR4), | ||
118 | REG_STRUCT_INIT(AR5K_IMR), | ||
119 | REG_STRUCT_INIT(AR5K_PIMR), | ||
120 | REG_STRUCT_INIT(AR5K_SIMR0), | ||
121 | REG_STRUCT_INIT(AR5K_SIMR1), | ||
122 | REG_STRUCT_INIT(AR5K_SIMR2), | ||
123 | REG_STRUCT_INIT(AR5K_SIMR3), | ||
124 | REG_STRUCT_INIT(AR5K_SIMR4), | ||
125 | REG_STRUCT_INIT(AR5K_DCM_ADDR), | ||
126 | REG_STRUCT_INIT(AR5K_DCCFG), | ||
127 | REG_STRUCT_INIT(AR5K_CCFG), | ||
128 | REG_STRUCT_INIT(AR5K_CPC0), | ||
129 | REG_STRUCT_INIT(AR5K_CPC1), | ||
130 | REG_STRUCT_INIT(AR5K_CPC2), | ||
131 | REG_STRUCT_INIT(AR5K_CPC3), | ||
132 | REG_STRUCT_INIT(AR5K_CPCORN), | ||
133 | REG_STRUCT_INIT(AR5K_RESET_CTL), | ||
134 | REG_STRUCT_INIT(AR5K_SLEEP_CTL), | ||
135 | REG_STRUCT_INIT(AR5K_INTPEND), | ||
136 | REG_STRUCT_INIT(AR5K_SFR), | ||
137 | REG_STRUCT_INIT(AR5K_PCICFG), | ||
138 | REG_STRUCT_INIT(AR5K_GPIOCR), | ||
139 | REG_STRUCT_INIT(AR5K_GPIODO), | ||
140 | REG_STRUCT_INIT(AR5K_SREV), | ||
141 | }; | ||
142 | |||
143 | static void *reg_start(struct seq_file *seq, loff_t *pos) | ||
144 | { | ||
145 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | ||
146 | } | ||
147 | |||
148 | static void reg_stop(struct seq_file *seq, void *p) | ||
149 | { | ||
150 | /* nothing to do */ | ||
151 | } | ||
152 | |||
153 | static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) | ||
154 | { | ||
155 | ++*pos; | ||
156 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | ||
157 | } | ||
158 | |||
159 | static int reg_show(struct seq_file *seq, void *p) | ||
160 | { | ||
161 | struct ath5k_softc *sc = seq->private; | ||
162 | struct reg *r = p; | ||
163 | seq_printf(seq, "%-25s0x%08x\n", r->name, | ||
164 | ath5k_hw_reg_read(sc->ah, r->addr)); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static struct seq_operations register_seq_ops = { | ||
169 | .start = reg_start, | ||
170 | .next = reg_next, | ||
171 | .stop = reg_stop, | ||
172 | .show = reg_show | ||
173 | }; | ||
174 | |||
175 | static int open_file_registers(struct inode *inode, struct file *file) | ||
176 | { | ||
177 | struct seq_file *s; | ||
178 | int res; | ||
179 | res = seq_open(file, ®ister_seq_ops); | ||
180 | if (res == 0) { | ||
181 | s = file->private_data; | ||
182 | s->private = inode->i_private; | ||
183 | } | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | static const struct file_operations fops_registers = { | ||
188 | .open = open_file_registers, | ||
189 | .read = seq_read, | ||
190 | .llseek = seq_lseek, | ||
191 | .release = seq_release, | ||
192 | .owner = THIS_MODULE, | ||
193 | }; | ||
194 | |||
195 | |||
196 | /* debugfs: TSF */ | ||
197 | |||
198 | static ssize_t read_file_tsf(struct file *file, char __user *user_buf, | ||
199 | size_t count, loff_t *ppos) | ||
200 | { | ||
201 | struct ath5k_softc *sc = file->private_data; | ||
202 | char buf[100]; | ||
203 | snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); | ||
204 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | ||
205 | } | ||
206 | |||
207 | static ssize_t write_file_tsf(struct file *file, | ||
208 | const char __user *userbuf, | ||
209 | size_t count, loff_t *ppos) | ||
210 | { | ||
211 | struct ath5k_softc *sc = file->private_data; | ||
212 | if (strncmp(userbuf, "reset", 5) == 0) { | ||
213 | ath5k_hw_reset_tsf(sc->ah); | ||
214 | printk(KERN_INFO "debugfs reset TSF\n"); | ||
215 | } | ||
216 | return count; | ||
217 | } | ||
218 | |||
219 | static const struct file_operations fops_tsf = { | ||
220 | .read = read_file_tsf, | ||
221 | .write = write_file_tsf, | ||
222 | .open = ath5k_debugfs_open, | ||
223 | .owner = THIS_MODULE, | ||
224 | }; | ||
225 | |||
226 | |||
227 | /* debugfs: beacons */ | ||
228 | |||
229 | static ssize_t read_file_beacon(struct file *file, char __user *user_buf, | ||
230 | size_t count, loff_t *ppos) | ||
231 | { | ||
232 | struct ath5k_softc *sc = file->private_data; | ||
233 | struct ath5k_hw *ah = sc->ah; | ||
234 | char buf[1000]; | ||
235 | int len = 0; | ||
236 | unsigned int v; | ||
237 | u64 tsf; | ||
238 | |||
239 | v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); | ||
240 | len += snprintf(buf+len, sizeof(buf)-len, | ||
241 | "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", | ||
242 | "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, | ||
243 | (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); | ||
244 | |||
245 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", | ||
246 | "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); | ||
247 | |||
248 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", | ||
249 | "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); | ||
250 | |||
251 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); | ||
252 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
253 | "AR5K_TIMER0 (TBTT)", v, v); | ||
254 | |||
255 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); | ||
256 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
257 | "AR5K_TIMER1 (DMA)", v, v >> 3); | ||
258 | |||
259 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); | ||
260 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
261 | "AR5K_TIMER2 (SWBA)", v, v >> 3); | ||
262 | |||
263 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); | ||
264 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
265 | "AR5K_TIMER3 (ATIM)", v, v); | ||
266 | |||
267 | tsf = ath5k_hw_get_tsf64(sc->ah); | ||
268 | len += snprintf(buf+len, sizeof(buf)-len, | ||
269 | "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf)); | ||
270 | |||
271 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
272 | } | ||
273 | |||
274 | static ssize_t write_file_beacon(struct file *file, | ||
275 | const char __user *userbuf, | ||
276 | size_t count, loff_t *ppos) | ||
277 | { | ||
278 | struct ath5k_softc *sc = file->private_data; | ||
279 | struct ath5k_hw *ah = sc->ah; | ||
280 | |||
281 | if (strncmp(userbuf, "disable", 7) == 0) { | ||
282 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | ||
283 | printk(KERN_INFO "debugfs disable beacons\n"); | ||
284 | } else if (strncmp(userbuf, "enable", 6) == 0) { | ||
285 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | ||
286 | printk(KERN_INFO "debugfs enable beacons\n"); | ||
287 | } | ||
288 | return count; | ||
289 | } | ||
290 | |||
291 | static const struct file_operations fops_beacon = { | ||
292 | .read = read_file_beacon, | ||
293 | .write = write_file_beacon, | ||
294 | .open = ath5k_debugfs_open, | ||
295 | .owner = THIS_MODULE, | ||
296 | }; | ||
297 | |||
298 | |||
299 | /* debugfs: reset */ | ||
300 | |||
301 | static ssize_t write_file_reset(struct file *file, | ||
302 | const char __user *userbuf, | ||
303 | size_t count, loff_t *ppos) | ||
304 | { | ||
305 | struct ath5k_softc *sc = file->private_data; | ||
306 | tasklet_schedule(&sc->restq); | ||
307 | return count; | ||
308 | } | ||
309 | |||
310 | static const struct file_operations fops_reset = { | ||
311 | .write = write_file_reset, | ||
312 | .open = ath5k_debugfs_open, | ||
313 | .owner = THIS_MODULE, | ||
314 | }; | ||
315 | |||
316 | |||
317 | /* init */ | ||
318 | |||
319 | void | ||
320 | ath5k_debug_init(void) | ||
321 | { | ||
322 | ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); | ||
323 | } | ||
324 | |||
325 | void | ||
326 | ath5k_debug_init_device(struct ath5k_softc *sc) | ||
327 | { | ||
328 | sc->debug.level = ath5k_debug; | ||
329 | sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | ||
330 | ath5k_global_debugfs); | ||
331 | sc->debug.debugfs_debug = debugfs_create_u32("debug", | ||
332 | 0666, sc->debug.debugfs_phydir, &sc->debug.level); | ||
333 | |||
334 | sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, | ||
335 | sc->debug.debugfs_phydir, | ||
336 | sc, &fops_registers); | ||
337 | |||
338 | sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, | ||
339 | sc->debug.debugfs_phydir, | ||
340 | sc, &fops_tsf); | ||
341 | |||
342 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, | ||
343 | sc->debug.debugfs_phydir, | ||
344 | sc, &fops_beacon); | ||
345 | |||
346 | sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, | ||
347 | sc->debug.debugfs_phydir, | ||
348 | sc, &fops_reset); | ||
349 | } | ||
350 | |||
351 | void | ||
352 | ath5k_debug_finish(void) | ||
353 | { | ||
354 | debugfs_remove(ath5k_global_debugfs); | ||
355 | } | ||
356 | |||
357 | void | ||
358 | ath5k_debug_finish_device(struct ath5k_softc *sc) | ||
359 | { | ||
360 | debugfs_remove(sc->debug.debugfs_debug); | ||
361 | debugfs_remove(sc->debug.debugfs_registers); | ||
362 | debugfs_remove(sc->debug.debugfs_tsf); | ||
363 | debugfs_remove(sc->debug.debugfs_beacon); | ||
364 | debugfs_remove(sc->debug.debugfs_reset); | ||
365 | debugfs_remove(sc->debug.debugfs_phydir); | ||
366 | } | ||
367 | |||
368 | |||
369 | /* functions used in other places */ | ||
370 | |||
371 | void | ||
372 | ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes) | ||
373 | { | ||
374 | unsigned int m, i; | ||
375 | |||
376 | if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES))) | ||
377 | return; | ||
378 | |||
379 | for (m = 0; m < NUM_DRIVER_MODES; m++) { | ||
380 | printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m, | ||
381 | modes[m].num_channels, modes[m].num_rates); | ||
382 | printk(KERN_DEBUG " channels:\n"); | ||
383 | for (i = 0; i < modes[m].num_channels; i++) | ||
384 | printk(KERN_DEBUG " %3d %d %.4x %.4x\n", | ||
385 | modes[m].channels[i].chan, | ||
386 | modes[m].channels[i].freq, | ||
387 | modes[m].channels[i].val, | ||
388 | modes[m].channels[i].flag); | ||
389 | printk(KERN_DEBUG " rates:\n"); | ||
390 | for (i = 0; i < modes[m].num_rates; i++) | ||
391 | printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", | ||
392 | modes[m].rates[i].rate, | ||
393 | modes[m].rates[i].val, | ||
394 | modes[m].rates[i].flags, | ||
395 | modes[m].rates[i].val2); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static inline void | ||
400 | ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) | ||
401 | { | ||
402 | struct ath5k_desc *ds = bf->desc; | ||
403 | |||
404 | printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", | ||
405 | ds, (unsigned long long)bf->daddr, | ||
406 | ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | ||
407 | ds->ds_hw[0], ds->ds_hw[1], | ||
408 | !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'); | ||
409 | } | ||
410 | |||
411 | void | ||
412 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | ||
413 | { | ||
414 | struct ath5k_desc *ds; | ||
415 | struct ath5k_buf *bf; | ||
416 | int status; | ||
417 | |||
418 | if (likely(!(sc->debug.level & | ||
419 | (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) | ||
420 | return; | ||
421 | |||
422 | printk(KERN_DEBUG "rx queue %x, link %p\n", | ||
423 | ath5k_hw_get_rx_buf(ah), sc->rxlink); | ||
424 | |||
425 | spin_lock_bh(&sc->rxbuflock); | ||
426 | list_for_each_entry(bf, &sc->rxbuf, list) { | ||
427 | ds = bf->desc; | ||
428 | status = ah->ah_proc_rx_desc(ah, ds); | ||
429 | if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) | ||
430 | ath5k_debug_printrxbuf(bf, status == 0); | ||
431 | } | ||
432 | spin_unlock_bh(&sc->rxbuflock); | ||
433 | } | ||
434 | |||
435 | void | ||
436 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
437 | struct sk_buff *skb, const char *prefix, int tx) | ||
438 | { | ||
439 | char buf[16]; | ||
440 | |||
441 | if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || | ||
442 | (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) | ||
443 | return; | ||
444 | |||
445 | snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); | ||
446 | |||
447 | print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, | ||
448 | min(200U, skb->len)); | ||
449 | |||
450 | printk(KERN_DEBUG "\n"); | ||
451 | } | ||
452 | |||
453 | void | ||
454 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | ||
455 | struct ath5k_buf *bf, int done) | ||
456 | { | ||
457 | struct ath5k_desc *ds = bf->desc; | ||
458 | |||
459 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | ||
460 | return; | ||
461 | |||
462 | printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " | ||
463 | "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, | ||
464 | ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | ||
465 | ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3], | ||
466 | !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); | ||
467 | } | ||
468 | |||
469 | #endif /* if ATH5K_DEBUG */ | ||
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h new file mode 100644 index 000000000000..2b491cbc8c80 --- /dev/null +++ b/drivers/net/wireless/ath5k/debug.h | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> | ||
3 | * | ||
4 | * This file is free software: you may copy, redistribute and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation, either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This file is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * | ||
18 | * This file incorporates work covered by the following copyright and | ||
19 | * permission notice: | ||
20 | * | ||
21 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
22 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
23 | * Copyright (c) 2006 Devicescape Software, Inc. | ||
24 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
25 | * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | ||
26 | * | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * 1. Redistributions of source code must retain the above copyright | ||
33 | * notice, this list of conditions and the following disclaimer, | ||
34 | * without modification. | ||
35 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
36 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
37 | * redistribution must be conditioned upon including a substantially | ||
38 | * similar Disclaimer requirement for further binary redistribution. | ||
39 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
40 | * of any contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * Alternatively, this software may be distributed under the terms of the | ||
44 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
45 | * Software Foundation. | ||
46 | * | ||
47 | * NO WARRANTY | ||
48 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
49 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
50 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
51 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
52 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
53 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
56 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
58 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
59 | */ | ||
60 | |||
61 | #ifndef _ATH5K_DEBUG_H | ||
62 | #define _ATH5K_DEBUG_H | ||
63 | |||
64 | /* set this to 1 for debugging output */ | ||
65 | #ifndef ATH5K_DEBUG | ||
66 | #define ATH5K_DEBUG 0 | ||
67 | #endif | ||
68 | |||
69 | struct ath5k_softc; | ||
70 | struct ath5k_hw; | ||
71 | struct ieee80211_hw_mode; | ||
72 | struct sk_buff; | ||
73 | struct ath5k_buf; | ||
74 | |||
75 | struct ath5k_dbg_info { | ||
76 | unsigned int level; /* debug level */ | ||
77 | /* debugfs entries */ | ||
78 | struct dentry *debugfs_phydir; | ||
79 | struct dentry *debugfs_debug; | ||
80 | struct dentry *debugfs_registers; | ||
81 | struct dentry *debugfs_tsf; | ||
82 | struct dentry *debugfs_beacon; | ||
83 | struct dentry *debugfs_reset; | ||
84 | }; | ||
85 | |||
86 | /** | ||
87 | * enum ath5k_debug_level - ath5k debug level | ||
88 | * | ||
89 | * @ATH5K_DEBUG_RESET: reset processing | ||
90 | * @ATH5K_DEBUG_INTR: interrupt handling | ||
91 | * @ATH5K_DEBUG_MODE: mode init/setup | ||
92 | * @ATH5K_DEBUG_XMIT: basic xmit operation | ||
93 | * @ATH5K_DEBUG_BEACON: beacon handling | ||
94 | * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc | ||
95 | * @ATH5K_DEBUG_CALIBRATE: periodic calibration | ||
96 | * @ATH5K_DEBUG_TXPOWER: transmit power setting | ||
97 | * @ATH5K_DEBUG_LED: led management | ||
98 | * @ATH5K_DEBUG_DUMP_RX: print received skb content | ||
99 | * @ATH5K_DEBUG_DUMP_TX: print transmit skb content | ||
100 | * @ATH5K_DEBUG_DUMPMODES: dump modes | ||
101 | * @ATH5K_DEBUG_TRACE: trace function calls | ||
102 | * @ATH5K_DEBUG_FATAL: fatal errors | ||
103 | * @ATH5K_DEBUG_ANY: show at any debug level | ||
104 | * | ||
105 | * The debug level is used to control the amount and type of debugging output | ||
106 | * we want to see. The debug level is given in calls to ATH5K_DBG to specify | ||
107 | * where the message should appear, and the user can control the debugging | ||
108 | * messages he wants to see, either by the module parameter 'debug' on module | ||
109 | * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can | ||
110 | * be combined together by bitwise OR. | ||
111 | */ | ||
112 | enum ath5k_debug_level { | ||
113 | ATH5K_DEBUG_RESET = 0x00000001, | ||
114 | ATH5K_DEBUG_INTR = 0x00000002, | ||
115 | ATH5K_DEBUG_MODE = 0x00000004, | ||
116 | ATH5K_DEBUG_XMIT = 0x00000008, | ||
117 | ATH5K_DEBUG_BEACON = 0x00000010, | ||
118 | ATH5K_DEBUG_BEACON_PROC = 0x00000020, | ||
119 | ATH5K_DEBUG_CALIBRATE = 0x00000100, | ||
120 | ATH5K_DEBUG_TXPOWER = 0x00000200, | ||
121 | ATH5K_DEBUG_LED = 0x00000400, | ||
122 | ATH5K_DEBUG_DUMP_RX = 0x00001000, | ||
123 | ATH5K_DEBUG_DUMP_TX = 0x00002000, | ||
124 | ATH5K_DEBUG_DUMPMODES = 0x00004000, | ||
125 | ATH5K_DEBUG_TRACE = 0x00010000, | ||
126 | ATH5K_DEBUG_FATAL = 0x80000000, | ||
127 | ATH5K_DEBUG_ANY = 0xffffffff | ||
128 | }; | ||
129 | |||
130 | #if ATH5K_DEBUG | ||
131 | |||
132 | #define ATH5K_TRACE(_sc) do { \ | ||
133 | if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ | ||
134 | printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ | ||
135 | } while (0) | ||
136 | |||
137 | #define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ | ||
138 | if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ | ||
139 | ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ | ||
140 | __func__, __LINE__, ##__VA_ARGS__); \ | ||
141 | } while (0) | ||
142 | |||
143 | #define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \ | ||
144 | if (unlikely((_sc)->debug.level & (_m))) \ | ||
145 | ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ | ||
146 | __func__, __LINE__, ##__VA_ARGS__); \ | ||
147 | } while (0) | ||
148 | |||
149 | void | ||
150 | ath5k_debug_init(void); | ||
151 | |||
152 | void | ||
153 | ath5k_debug_init_device(struct ath5k_softc *sc); | ||
154 | |||
155 | void | ||
156 | ath5k_debug_finish(void); | ||
157 | |||
158 | void | ||
159 | ath5k_debug_finish_device(struct ath5k_softc *sc); | ||
160 | |||
161 | void | ||
162 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); | ||
163 | |||
164 | void | ||
165 | ath5k_debug_dump_modes(struct ath5k_softc *sc, | ||
166 | struct ieee80211_hw_mode *modes); | ||
167 | |||
168 | void | ||
169 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
170 | struct sk_buff *skb, const char *prefix, int tx); | ||
171 | |||
172 | void | ||
173 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | ||
174 | struct ath5k_buf *bf, int done); | ||
175 | |||
176 | #else /* no debugging */ | ||
177 | |||
178 | #define ATH5K_TRACE(_sc) /* empty */ | ||
179 | |||
180 | static inline void __attribute__ ((format (printf, 3, 4))) | ||
181 | ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} | ||
182 | |||
183 | static inline void __attribute__ ((format (printf, 3, 4))) | ||
184 | ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) | ||
185 | {} | ||
186 | |||
187 | static inline void | ||
188 | ath5k_debug_init(void) {} | ||
189 | |||
190 | static inline void | ||
191 | ath5k_debug_init_device(struct ath5k_softc *sc) {} | ||
192 | |||
193 | static inline void | ||
194 | ath5k_debug_finish(void) {} | ||
195 | |||
196 | static inline void | ||
197 | ath5k_debug_finish_device(struct ath5k_softc *sc) {} | ||
198 | |||
199 | static inline void | ||
200 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} | ||
201 | |||
202 | static inline void | ||
203 | ath5k_debug_dump_modes(struct ath5k_softc *sc, | ||
204 | struct ieee80211_hw_mode *modes) {} | ||
205 | |||
206 | static inline void | ||
207 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
208 | struct sk_buff *skb, const char *prefix, int tx) {} | ||
209 | |||
210 | static inline void | ||
211 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | ||
212 | struct ath5k_buf *bf, int done) {} | ||
213 | |||
214 | #endif /* if ATH5K_DEBUG */ | ||
215 | |||
216 | #endif /* ifndef _ATH5K_DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c new file mode 100644 index 000000000000..5623d7dc738e --- /dev/null +++ b/drivers/net/wireless/ath5k/hw.c | |||
@@ -0,0 +1,4349 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org> | ||
5 | * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
6 | * Copyright (c) 2007 Pavel Roskin <proski@gnu.org> | ||
7 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
8 | * | ||
9 | * Permission to use, copy, modify, and distribute this software for any | ||
10 | * purpose with or without fee is hereby granted, provided that the above | ||
11 | * copyright notice and this permission notice appear in all copies. | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * HW related functions for Atheros Wireless LAN devices. | ||
25 | */ | ||
26 | |||
27 | #include <linux/pci.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #include "reg.h" | ||
31 | #include "base.h" | ||
32 | #include "debug.h" | ||
33 | |||
34 | /*Rate tables*/ | ||
35 | static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A; | ||
36 | static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B; | ||
37 | static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G; | ||
38 | static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO; | ||
39 | static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR; | ||
40 | |||
41 | /*Prototypes*/ | ||
42 | static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); | ||
43 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); | ||
44 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
45 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | ||
46 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
47 | unsigned int, unsigned int); | ||
48 | static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
49 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
50 | unsigned int); | ||
51 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *); | ||
52 | static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, | ||
53 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | ||
54 | unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, | ||
55 | unsigned int, unsigned int); | ||
56 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *); | ||
57 | static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *); | ||
58 | static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *); | ||
59 | static int ath5k_hw_get_capabilities(struct ath5k_hw *); | ||
60 | |||
61 | static int ath5k_eeprom_init(struct ath5k_hw *); | ||
62 | static int ath5k_eeprom_read_mac(struct ath5k_hw *, u8 *); | ||
63 | |||
64 | static int ath5k_hw_enable_pspoll(struct ath5k_hw *, u8 *, u16); | ||
65 | static int ath5k_hw_disable_pspoll(struct ath5k_hw *); | ||
66 | |||
67 | /* | ||
68 | * Enable to overwrite the country code (use "00" for debug) | ||
69 | */ | ||
70 | #if 0 | ||
71 | #define COUNTRYCODE "00" | ||
72 | #endif | ||
73 | |||
74 | /*******************\ | ||
75 | General Functions | ||
76 | \*******************/ | ||
77 | |||
78 | /* | ||
79 | * Functions used internaly | ||
80 | */ | ||
81 | |||
82 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
83 | { | ||
84 | return turbo == true ? (usec * 80) : (usec * 40); | ||
85 | } | ||
86 | |||
87 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
88 | { | ||
89 | return turbo == true ? (clock / 80) : (clock / 40); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Check if a register write has been completed | ||
94 | */ | ||
95 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
96 | bool is_set) | ||
97 | { | ||
98 | int i; | ||
99 | u32 data; | ||
100 | |||
101 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
102 | data = ath5k_hw_reg_read(ah, reg); | ||
103 | if ((is_set == true) && (data & flag)) | ||
104 | break; | ||
105 | else if ((data & flag) == val) | ||
106 | break; | ||
107 | udelay(15); | ||
108 | } | ||
109 | |||
110 | return (i <= 0) ? -EAGAIN : 0; | ||
111 | } | ||
112 | |||
113 | |||
114 | /***************************************\ | ||
115 | Attach/Detach Functions | ||
116 | \***************************************/ | ||
117 | |||
118 | /* | ||
119 | * Check if the device is supported and initialize the needed structs | ||
120 | */ | ||
121 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | ||
122 | { | ||
123 | struct ath5k_hw *ah; | ||
124 | u8 mac[ETH_ALEN]; | ||
125 | int ret; | ||
126 | u32 srev; | ||
127 | |||
128 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
129 | ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
130 | if (ah == NULL) { | ||
131 | ret = -ENOMEM; | ||
132 | ATH5K_ERR(sc, "out of memory\n"); | ||
133 | goto err; | ||
134 | } | ||
135 | |||
136 | ah->ah_sc = sc; | ||
137 | ah->ah_iobase = sc->iobase; | ||
138 | |||
139 | /* | ||
140 | * HW information | ||
141 | */ | ||
142 | |||
143 | /* Get reg domain from eeprom */ | ||
144 | ath5k_get_regdomain(ah); | ||
145 | |||
146 | ah->ah_op_mode = IEEE80211_IF_TYPE_STA; | ||
147 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | ||
148 | ah->ah_turbo = false; | ||
149 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
150 | ah->ah_imr = 0; | ||
151 | ah->ah_atim_window = 0; | ||
152 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
153 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
154 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | ||
155 | ah->ah_software_retry = false; | ||
156 | ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; | ||
157 | |||
158 | /* | ||
159 | * Set the mac revision based on the pci id | ||
160 | */ | ||
161 | ah->ah_version = mac_version; | ||
162 | |||
163 | /*Fill the ath5k_hw struct with the needed functions*/ | ||
164 | if (ah->ah_version == AR5K_AR5212) | ||
165 | ah->ah_magic = AR5K_EEPROM_MAGIC_5212; | ||
166 | else if (ah->ah_version == AR5K_AR5211) | ||
167 | ah->ah_magic = AR5K_EEPROM_MAGIC_5211; | ||
168 | |||
169 | if (ah->ah_version == AR5K_AR5212) { | ||
170 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | ||
171 | ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc; | ||
172 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; | ||
173 | } else { | ||
174 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | ||
175 | ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc; | ||
176 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | ||
177 | } | ||
178 | |||
179 | if (ah->ah_version == AR5K_AR5212) | ||
180 | ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status; | ||
181 | else if (ah->ah_version <= AR5K_AR5211) | ||
182 | ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status; | ||
183 | |||
184 | /* Bring device out of sleep and reset it's units */ | ||
185 | ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true); | ||
186 | if (ret) | ||
187 | goto err_free; | ||
188 | |||
189 | /* Get MAC, PHY and RADIO revisions */ | ||
190 | srev = ath5k_hw_reg_read(ah, AR5K_SREV); | ||
191 | ah->ah_mac_srev = srev; | ||
192 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | ||
193 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
194 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | ||
195 | 0xffffffff; | ||
196 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | ||
197 | CHANNEL_5GHZ); | ||
198 | |||
199 | if (ah->ah_version == AR5K_AR5210) | ||
200 | ah->ah_radio_2ghz_revision = 0; | ||
201 | else | ||
202 | ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, | ||
203 | CHANNEL_2GHZ); | ||
204 | |||
205 | /* Return on unsuported chips (unsupported eeprom etc) */ | ||
206 | if(srev >= AR5K_SREV_VER_AR5416){ | ||
207 | ATH5K_ERR(sc, "Device not yet supported.\n"); | ||
208 | ret = -ENODEV; | ||
209 | goto err_free; | ||
210 | } | ||
211 | |||
212 | /* Identify single chip solutions */ | ||
213 | if((srev <= AR5K_SREV_VER_AR5414) && | ||
214 | (srev >= AR5K_SREV_VER_AR2424)) { | ||
215 | ah->ah_single_chip = true; | ||
216 | } else { | ||
217 | ah->ah_single_chip = false; | ||
218 | } | ||
219 | |||
220 | /* Single chip radio */ | ||
221 | if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision) | ||
222 | ah->ah_radio_2ghz_revision = 0; | ||
223 | |||
224 | /* Identify the radio chip*/ | ||
225 | if (ah->ah_version == AR5K_AR5210) { | ||
226 | ah->ah_radio = AR5K_RF5110; | ||
227 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { | ||
228 | ah->ah_radio = AR5K_RF5111; | ||
229 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | ||
230 | ah->ah_radio = AR5K_RF5112; | ||
231 | } else { | ||
232 | ah->ah_radio = AR5K_RF5413; | ||
233 | } | ||
234 | |||
235 | ah->ah_phy = AR5K_PHY(0); | ||
236 | |||
237 | /* | ||
238 | * Get card capabilities, values, ... | ||
239 | */ | ||
240 | |||
241 | ret = ath5k_eeprom_init(ah); | ||
242 | if (ret) { | ||
243 | ATH5K_ERR(sc, "unable to init EEPROM\n"); | ||
244 | goto err_free; | ||
245 | } | ||
246 | |||
247 | /* Get misc capabilities */ | ||
248 | ret = ath5k_hw_get_capabilities(ah); | ||
249 | if (ret) { | ||
250 | ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", | ||
251 | sc->pdev->device); | ||
252 | goto err_free; | ||
253 | } | ||
254 | |||
255 | /* Get MAC address */ | ||
256 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
257 | if (ret) { | ||
258 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
259 | sc->pdev->device); | ||
260 | goto err_free; | ||
261 | } | ||
262 | |||
263 | ath5k_hw_set_lladdr(ah, mac); | ||
264 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | ||
265 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | ||
266 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
267 | ath5k_hw_set_opmode(ah); | ||
268 | |||
269 | ath5k_hw_set_rfgain_opt(ah); | ||
270 | |||
271 | return ah; | ||
272 | err_free: | ||
273 | kfree(ah); | ||
274 | err: | ||
275 | return ERR_PTR(ret); | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Bring up MAC + PHY Chips | ||
280 | */ | ||
281 | static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | ||
282 | { | ||
283 | u32 turbo, mode, clock; | ||
284 | int ret; | ||
285 | |||
286 | turbo = 0; | ||
287 | mode = 0; | ||
288 | clock = 0; | ||
289 | |||
290 | ATH5K_TRACE(ah->ah_sc); | ||
291 | |||
292 | /* Wakeup the device */ | ||
293 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
294 | if (ret) { | ||
295 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | if (ah->ah_version != AR5K_AR5210) { | ||
300 | /* | ||
301 | * Get channel mode flags | ||
302 | */ | ||
303 | |||
304 | if (ah->ah_radio >= AR5K_RF5112) { | ||
305 | mode = AR5K_PHY_MODE_RAD_RF5112; | ||
306 | clock = AR5K_PHY_PLL_RF5112; | ||
307 | } else { | ||
308 | mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ | ||
309 | clock = AR5K_PHY_PLL_RF5111; /*Zero*/ | ||
310 | } | ||
311 | |||
312 | if (flags & CHANNEL_2GHZ) { | ||
313 | mode |= AR5K_PHY_MODE_FREQ_2GHZ; | ||
314 | clock |= AR5K_PHY_PLL_44MHZ; | ||
315 | |||
316 | if (flags & CHANNEL_CCK) { | ||
317 | mode |= AR5K_PHY_MODE_MOD_CCK; | ||
318 | } else if (flags & CHANNEL_OFDM) { | ||
319 | /* XXX Dynamic OFDM/CCK is not supported by the | ||
320 | * AR5211 so we set MOD_OFDM for plain g (no | ||
321 | * CCK headers) operation. We need to test | ||
322 | * this, 5211 might support ofdm-only g after | ||
323 | * all, there are also initial register values | ||
324 | * in the code for g mode (see initvals.c). */ | ||
325 | if (ah->ah_version == AR5K_AR5211) | ||
326 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
327 | else | ||
328 | mode |= AR5K_PHY_MODE_MOD_DYN; | ||
329 | } else { | ||
330 | ATH5K_ERR(ah->ah_sc, | ||
331 | "invalid radio modulation mode\n"); | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | } else if (flags & CHANNEL_5GHZ) { | ||
335 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; | ||
336 | clock |= AR5K_PHY_PLL_40MHZ; | ||
337 | |||
338 | if (flags & CHANNEL_OFDM) | ||
339 | mode |= AR5K_PHY_MODE_MOD_OFDM; | ||
340 | else { | ||
341 | ATH5K_ERR(ah->ah_sc, | ||
342 | "invalid radio modulation mode\n"); | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | } else { | ||
346 | ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
350 | if (flags & CHANNEL_TURBO) | ||
351 | turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; | ||
352 | } else { /* Reset the device */ | ||
353 | |||
354 | /* ...enable Atheros turbo mode if requested */ | ||
355 | if (flags & CHANNEL_TURBO) | ||
356 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, | ||
357 | AR5K_PHY_TURBO); | ||
358 | } | ||
359 | |||
360 | /* ...reset chipset and PCI device */ | ||
361 | if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah, | ||
362 | AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) { | ||
363 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); | ||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | if (ah->ah_version == AR5K_AR5210) | ||
368 | udelay(2300); | ||
369 | |||
370 | /* ...wakeup again!*/ | ||
371 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | ||
372 | if (ret) { | ||
373 | ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); | ||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | /* ...final warm reset */ | ||
378 | if (ath5k_hw_nic_reset(ah, 0)) { | ||
379 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | ||
380 | return -EIO; | ||
381 | } | ||
382 | |||
383 | if (ah->ah_version != AR5K_AR5210) { | ||
384 | /* ...set the PHY operating mode */ | ||
385 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); | ||
386 | udelay(300); | ||
387 | |||
388 | ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); | ||
389 | ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); | ||
390 | } | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Get the rate table for a specific operation mode | ||
397 | */ | ||
398 | const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, | ||
399 | unsigned int mode) | ||
400 | { | ||
401 | ATH5K_TRACE(ah->ah_sc); | ||
402 | |||
403 | if (!test_bit(mode, ah->ah_capabilities.cap_mode)) | ||
404 | return NULL; | ||
405 | |||
406 | /* Get rate tables */ | ||
407 | switch (mode) { | ||
408 | case MODE_IEEE80211A: | ||
409 | return &ath5k_rt_11a; | ||
410 | case MODE_ATHEROS_TURBO: | ||
411 | return &ath5k_rt_turbo; | ||
412 | case MODE_IEEE80211B: | ||
413 | return &ath5k_rt_11b; | ||
414 | case MODE_IEEE80211G: | ||
415 | return &ath5k_rt_11g; | ||
416 | case MODE_ATHEROS_TURBOG: | ||
417 | return &ath5k_rt_xr; | ||
418 | } | ||
419 | |||
420 | return NULL; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * Free the ath5k_hw struct | ||
425 | */ | ||
426 | void ath5k_hw_detach(struct ath5k_hw *ah) | ||
427 | { | ||
428 | ATH5K_TRACE(ah->ah_sc); | ||
429 | |||
430 | if (ah->ah_rf_banks != NULL) | ||
431 | kfree(ah->ah_rf_banks); | ||
432 | |||
433 | /* assume interrupts are down */ | ||
434 | kfree(ah); | ||
435 | } | ||
436 | |||
437 | /****************************\ | ||
438 | Reset function and helpers | ||
439 | \****************************/ | ||
440 | |||
441 | /** | ||
442 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
443 | * | ||
444 | * @ah: the &struct ath5k_hw | ||
445 | * @channel: the currently set channel upon reset | ||
446 | * | ||
447 | * Write the OFDM timings for the AR5212 upon reset. This is a helper for | ||
448 | * ath5k_hw_reset(). This seems to tune the PLL a specified frequency | ||
449 | * depending on the bandwidth of the channel. | ||
450 | * | ||
451 | */ | ||
452 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
453 | struct ieee80211_channel *channel) | ||
454 | { | ||
455 | /* Get exponent and mantissa and set it */ | ||
456 | u32 coef_scaled, coef_exp, coef_man, | ||
457 | ds_coef_exp, ds_coef_man, clock; | ||
458 | |||
459 | if (!(ah->ah_version == AR5K_AR5212) || | ||
460 | !(channel->val & CHANNEL_OFDM)) | ||
461 | BUG(); | ||
462 | |||
463 | /* Seems there are two PLLs, one for baseband sampling and one | ||
464 | * for tuning. Tuning basebands are 40 MHz or 80MHz when in | ||
465 | * turbo. */ | ||
466 | clock = channel->val & CHANNEL_TURBO ? 80 : 40; | ||
467 | coef_scaled = ((5 * (clock << 24)) / 2) / | ||
468 | channel->freq; | ||
469 | |||
470 | for (coef_exp = 31; coef_exp > 0; coef_exp--) | ||
471 | if ((coef_scaled >> coef_exp) & 0x1) | ||
472 | break; | ||
473 | |||
474 | if (!coef_exp) | ||
475 | return -EINVAL; | ||
476 | |||
477 | coef_exp = 14 - (coef_exp - 24); | ||
478 | coef_man = coef_scaled + | ||
479 | (1 << (24 - coef_exp - 1)); | ||
480 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
481 | ds_coef_exp = coef_exp - 16; | ||
482 | |||
483 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
484 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
485 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
486 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /** | ||
492 | * ath5k_hw_write_rate_duration - set rate duration during hw resets | ||
493 | * | ||
494 | * @ah: the &struct ath5k_hw | ||
495 | * @driver_mode: one of enum ieee80211_phymode or our one of our own | ||
496 | * vendor modes | ||
497 | * | ||
498 | * Write the rate duration table for the current mode upon hw reset. This | ||
499 | * is a helper for ath5k_hw_reset(). It seems all this is doing is setting | ||
500 | * an ACK timeout for the hardware for the current mode for each rate. The | ||
501 | * rates which are capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, | ||
502 | * and 11Mbps) have another register for the short preamble ACK timeout | ||
503 | * calculation. | ||
504 | * | ||
505 | */ | ||
506 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | ||
507 | unsigned int driver_mode) | ||
508 | { | ||
509 | struct ath5k_softc *sc = ah->ah_sc; | ||
510 | const struct ath5k_rate_table *rt; | ||
511 | unsigned int i; | ||
512 | |||
513 | /* Get rate table for the current operating mode */ | ||
514 | rt = ath5k_hw_get_rate_table(ah, | ||
515 | driver_mode); | ||
516 | |||
517 | /* Write rate duration table */ | ||
518 | for (i = 0; i < rt->rate_count; i++) { | ||
519 | const struct ath5k_rate *rate, *control_rate; | ||
520 | u32 reg; | ||
521 | u16 tx_time; | ||
522 | |||
523 | rate = &rt->rates[i]; | ||
524 | control_rate = &rt->rates[rate->control_rate]; | ||
525 | |||
526 | /* Set ACK timeout */ | ||
527 | reg = AR5K_RATE_DUR(rate->rate_code); | ||
528 | |||
529 | /* An ACK frame consists of 10 bytes. If you add the FCS, | ||
530 | * which ieee80211_generic_frame_duration() adds, | ||
531 | * its 14 bytes. Note we use the control rate and not the | ||
532 | * actual rate for this rate. See mac80211 tx.c | ||
533 | * ieee80211_duration() for a brief description of | ||
534 | * what rate we should choose to TX ACKs. */ | ||
535 | tx_time = ieee80211_generic_frame_duration(sc->hw, | ||
536 | sc->iface_id, 10, control_rate->rate_kbps/100); | ||
537 | |||
538 | ath5k_hw_reg_write(ah, tx_time, reg); | ||
539 | |||
540 | if (!HAS_SHPREAMBLE(i)) | ||
541 | continue; | ||
542 | |||
543 | /* | ||
544 | * We're not distinguishing short preamble here, | ||
545 | * This is true, all we'll get is a longer value here | ||
546 | * which is not necessarilly bad. We could use | ||
547 | * export ieee80211_frame_duration() but that needs to be | ||
548 | * fixed first to be properly used by mac802111 drivers: | ||
549 | * | ||
550 | * - remove erp stuff and let the routine figure ofdm | ||
551 | * erp rates | ||
552 | * - remove passing argument ieee80211_local as | ||
553 | * drivers don't have access to it | ||
554 | * - move drivers using ieee80211_generic_frame_duration() | ||
555 | * to this | ||
556 | */ | ||
557 | ath5k_hw_reg_write(ah, tx_time, | ||
558 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * Main reset function | ||
564 | */ | ||
565 | int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | ||
566 | struct ieee80211_channel *channel, bool change_channel) | ||
567 | { | ||
568 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
569 | u32 data, s_seq, s_ant, s_led[3]; | ||
570 | unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1; | ||
571 | int ret; | ||
572 | |||
573 | ATH5K_TRACE(ah->ah_sc); | ||
574 | |||
575 | s_seq = 0; | ||
576 | s_ant = 0; | ||
577 | ee_mode = 0; | ||
578 | freq = 0; | ||
579 | mode = 0; | ||
580 | |||
581 | /* | ||
582 | * Save some registers before a reset | ||
583 | */ | ||
584 | /*DCU/Antenna selection not available on 5210*/ | ||
585 | if (ah->ah_version != AR5K_AR5210) { | ||
586 | if (change_channel == true) { | ||
587 | /* Seq number for queue 0 -do this for all queues ? */ | ||
588 | s_seq = ath5k_hw_reg_read(ah, | ||
589 | AR5K_QUEUE_DFS_SEQNUM(0)); | ||
590 | /*Default antenna*/ | ||
591 | s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /*GPIOs*/ | ||
596 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; | ||
597 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); | ||
598 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
599 | |||
600 | if (change_channel == true && ah->ah_rf_banks != NULL) | ||
601 | ath5k_hw_get_rf_gain(ah); | ||
602 | |||
603 | |||
604 | /*Wakeup the device*/ | ||
605 | ret = ath5k_hw_nic_wakeup(ah, channel->val, false); | ||
606 | if (ret) | ||
607 | return ret; | ||
608 | |||
609 | /* | ||
610 | * Initialize operating mode | ||
611 | */ | ||
612 | ah->ah_op_mode = op_mode; | ||
613 | |||
614 | /* | ||
615 | * 5111/5112 Settings | ||
616 | * 5210 only comes with RF5110 | ||
617 | */ | ||
618 | if (ah->ah_version != AR5K_AR5210) { | ||
619 | if (ah->ah_radio != AR5K_RF5111 && | ||
620 | ah->ah_radio != AR5K_RF5112 && | ||
621 | ah->ah_radio != AR5K_RF5413) { | ||
622 | ATH5K_ERR(ah->ah_sc, | ||
623 | "invalid phy radio: %u\n", ah->ah_radio); | ||
624 | return -EINVAL; | ||
625 | } | ||
626 | |||
627 | switch (channel->val & CHANNEL_MODES) { | ||
628 | case CHANNEL_A: | ||
629 | mode = AR5K_INI_VAL_11A; | ||
630 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
631 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
632 | driver_mode = MODE_IEEE80211A; | ||
633 | break; | ||
634 | case CHANNEL_G: | ||
635 | mode = AR5K_INI_VAL_11G; | ||
636 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
637 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
638 | driver_mode = MODE_IEEE80211G; | ||
639 | break; | ||
640 | case CHANNEL_B: | ||
641 | mode = AR5K_INI_VAL_11B; | ||
642 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
643 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
644 | driver_mode = MODE_IEEE80211B; | ||
645 | break; | ||
646 | case CHANNEL_T: | ||
647 | mode = AR5K_INI_VAL_11A_TURBO; | ||
648 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
649 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
650 | driver_mode = MODE_ATHEROS_TURBO; | ||
651 | break; | ||
652 | /*Is this ok on 5211 too ?*/ | ||
653 | case CHANNEL_TG: | ||
654 | mode = AR5K_INI_VAL_11G_TURBO; | ||
655 | freq = AR5K_INI_RFGAIN_2GHZ; | ||
656 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
657 | driver_mode = MODE_ATHEROS_TURBOG; | ||
658 | break; | ||
659 | case CHANNEL_XR: | ||
660 | if (ah->ah_version == AR5K_AR5211) { | ||
661 | ATH5K_ERR(ah->ah_sc, | ||
662 | "XR mode not available on 5211"); | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | mode = AR5K_INI_VAL_XR; | ||
666 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
667 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
668 | driver_mode = MODE_IEEE80211A; | ||
669 | break; | ||
670 | default: | ||
671 | ATH5K_ERR(ah->ah_sc, | ||
672 | "invalid channel: %d\n", channel->freq); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | |||
676 | /* PHY access enable */ | ||
677 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
678 | |||
679 | } | ||
680 | |||
681 | ret = ath5k_hw_write_initvals(ah, mode, change_channel); | ||
682 | if (ret) | ||
683 | return ret; | ||
684 | |||
685 | /* | ||
686 | * 5211/5212 Specific | ||
687 | */ | ||
688 | if (ah->ah_version != AR5K_AR5210) { | ||
689 | /* | ||
690 | * Write initial RF gain settings | ||
691 | * This should work for both 5111/5112 | ||
692 | */ | ||
693 | ret = ath5k_hw_rfgain(ah, freq); | ||
694 | if (ret) | ||
695 | return ret; | ||
696 | |||
697 | mdelay(1); | ||
698 | |||
699 | /* | ||
700 | * Write some more initial register settings | ||
701 | */ | ||
702 | if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */ | ||
703 | ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); | ||
704 | |||
705 | if (channel->val == CHANNEL_G) | ||
706 | ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */ | ||
707 | else | ||
708 | ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83)); | ||
709 | |||
710 | ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */ | ||
711 | ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); | ||
712 | ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); | ||
713 | ath5k_hw_reg_write(ah, 0x00000000, 0xa254); | ||
714 | ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); | ||
715 | } | ||
716 | |||
717 | /* Fix for first revision of the RF5112 RF chipset */ | ||
718 | if (ah->ah_radio >= AR5K_RF5112 && | ||
719 | ah->ah_radio_5ghz_revision < | ||
720 | AR5K_SREV_RAD_5112A) { | ||
721 | ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, | ||
722 | AR5K_PHY_CCKTXCTL); | ||
723 | if (channel->val & CHANNEL_5GHZ) | ||
724 | data = 0xffb81020; | ||
725 | else | ||
726 | data = 0xffb80d20; | ||
727 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); | ||
728 | } | ||
729 | |||
730 | /* | ||
731 | * Set TX power (FIXME) | ||
732 | */ | ||
733 | ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER); | ||
734 | if (ret) | ||
735 | return ret; | ||
736 | |||
737 | /* Write rate duration table */ | ||
738 | if (ah->ah_version == AR5K_AR5212) | ||
739 | ath5k_hw_write_rate_duration(ah, driver_mode); | ||
740 | |||
741 | /* | ||
742 | * Write RF registers | ||
743 | * TODO:Does this work on 5211 (5111) ? | ||
744 | */ | ||
745 | ret = ath5k_hw_rfregs(ah, channel, mode); | ||
746 | if (ret) | ||
747 | return ret; | ||
748 | |||
749 | /* | ||
750 | * Configure additional registers | ||
751 | */ | ||
752 | |||
753 | /* Write OFDM timings on 5212*/ | ||
754 | if (ah->ah_version == AR5K_AR5212 && | ||
755 | channel->val & CHANNEL_OFDM) { | ||
756 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
757 | if (ret) | ||
758 | return ret; | ||
759 | } | ||
760 | |||
761 | /*Enable/disable 802.11b mode on 5111 | ||
762 | (enable 2111 frequency converter + CCK)*/ | ||
763 | if (ah->ah_radio == AR5K_RF5111) { | ||
764 | if (driver_mode == MODE_IEEE80211B) | ||
765 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
766 | AR5K_TXCFG_B_MODE); | ||
767 | else | ||
768 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
769 | AR5K_TXCFG_B_MODE); | ||
770 | } | ||
771 | |||
772 | /* | ||
773 | * Set channel and calibrate the PHY | ||
774 | */ | ||
775 | ret = ath5k_hw_channel(ah, channel); | ||
776 | if (ret) | ||
777 | return ret; | ||
778 | |||
779 | /* Set antenna mode */ | ||
780 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44), | ||
781 | ah->ah_antenna[ee_mode][0], 0xfffffc06); | ||
782 | |||
783 | /* | ||
784 | * In case a fixed antenna was set as default | ||
785 | * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE | ||
786 | * registers. | ||
787 | */ | ||
788 | if (s_ant != 0){ | ||
789 | if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ | ||
790 | ant[0] = ant[1] = AR5K_ANT_FIXED_A; | ||
791 | else /* 2 - Aux */ | ||
792 | ant[0] = ant[1] = AR5K_ANT_FIXED_B; | ||
793 | } else { | ||
794 | ant[0] = AR5K_ANT_FIXED_A; | ||
795 | ant[1] = AR5K_ANT_FIXED_B; | ||
796 | } | ||
797 | |||
798 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], | ||
799 | AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
800 | ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], | ||
801 | AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
802 | |||
803 | /* Commit values from EEPROM */ | ||
804 | if (ah->ah_radio == AR5K_RF5111) | ||
805 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, | ||
806 | AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip); | ||
807 | |||
808 | ath5k_hw_reg_write(ah, | ||
809 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), | ||
810 | AR5K_PHY(0x5a)); | ||
811 | |||
812 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11), | ||
813 | (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, | ||
814 | 0xffffc07f); | ||
815 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12), | ||
816 | (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, | ||
817 | 0xfffc0fff); | ||
818 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14), | ||
819 | (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | | ||
820 | ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), | ||
821 | 0xffff0000); | ||
822 | |||
823 | ath5k_hw_reg_write(ah, | ||
824 | (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | | ||
825 | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | | ||
826 | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | | ||
827 | (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d)); | ||
828 | |||
829 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a), | ||
830 | ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); | ||
831 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19), | ||
832 | (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); | ||
833 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01); | ||
834 | |||
835 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
836 | AR5K_PHY_IQ_CORR_ENABLE | | ||
837 | (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | | ||
838 | ee->ee_q_cal[ee_mode]); | ||
839 | |||
840 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
841 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, | ||
842 | AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, | ||
843 | ee->ee_margin_tx_rx[ee_mode]); | ||
844 | |||
845 | } else { | ||
846 | mdelay(1); | ||
847 | /* Disable phy and wait */ | ||
848 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
849 | mdelay(1); | ||
850 | } | ||
851 | |||
852 | /* | ||
853 | * Restore saved values | ||
854 | */ | ||
855 | /*DCU/Antenna selection not available on 5210*/ | ||
856 | if (ah->ah_version != AR5K_AR5210) { | ||
857 | ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0)); | ||
858 | ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); | ||
859 | } | ||
860 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); | ||
861 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); | ||
862 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | ||
863 | |||
864 | /* | ||
865 | * Misc | ||
866 | */ | ||
867 | /* XXX: add ah->aid once mac80211 gives this to us */ | ||
868 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
869 | |||
870 | ath5k_hw_set_opmode(ah); | ||
871 | /*PISR/SISR Not available on 5210*/ | ||
872 | if (ah->ah_version != AR5K_AR5210) { | ||
873 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
874 | /* If we later allow tuning for this, store into sc structure */ | ||
875 | data = AR5K_TUNE_RSSI_THRES | | ||
876 | AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S; | ||
877 | ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR); | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * Set Rx/Tx DMA Configuration | ||
882 | *(passing dma size not available on 5210) | ||
883 | */ | ||
884 | if (ah->ah_version != AR5K_AR5210) { | ||
885 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR, | ||
886 | AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE); | ||
887 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW, | ||
888 | AR5K_DMASIZE_512B); | ||
889 | } | ||
890 | |||
891 | /* | ||
892 | * Enable the PHY and wait until completion | ||
893 | */ | ||
894 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
895 | |||
896 | /* | ||
897 | * 5111/5112 Specific | ||
898 | */ | ||
899 | if (ah->ah_version != AR5K_AR5210) { | ||
900 | data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
901 | AR5K_PHY_RX_DELAY_M; | ||
902 | data = (channel->val & CHANNEL_CCK) ? | ||
903 | ((data << 2) / 22) : (data / 10); | ||
904 | |||
905 | udelay(100 + data); | ||
906 | } else { | ||
907 | mdelay(1); | ||
908 | } | ||
909 | |||
910 | /* | ||
911 | * Enable calibration and wait until completion | ||
912 | */ | ||
913 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
914 | AR5K_PHY_AGCCTL_CAL); | ||
915 | |||
916 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
917 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
918 | ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", | ||
919 | channel->freq); | ||
920 | return -EAGAIN; | ||
921 | } | ||
922 | |||
923 | ret = ath5k_hw_noise_floor_calibration(ah, channel->freq); | ||
924 | if (ret) | ||
925 | return ret; | ||
926 | |||
927 | ah->ah_calibration = false; | ||
928 | |||
929 | /* A and G modes can use QAM modulation which requires enabling | ||
930 | * I and Q calibration. Don't bother in B mode. */ | ||
931 | if (!(driver_mode == MODE_IEEE80211B)) { | ||
932 | ah->ah_calibration = true; | ||
933 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
934 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
935 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
936 | AR5K_PHY_IQ_RUN); | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Reset queues and start beacon timers at the end of the reset routine | ||
941 | */ | ||
942 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
943 | /*No QCU on 5210*/ | ||
944 | if (ah->ah_version != AR5K_AR5210) | ||
945 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i); | ||
946 | |||
947 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
948 | if (ret) { | ||
949 | ATH5K_ERR(ah->ah_sc, | ||
950 | "failed to reset TX queue #%d\n", i); | ||
951 | return ret; | ||
952 | } | ||
953 | } | ||
954 | |||
955 | /* Pre-enable interrupts on 5211/5212*/ | ||
956 | if (ah->ah_version != AR5K_AR5210) | ||
957 | ath5k_hw_set_intr(ah, AR5K_INT_RX | AR5K_INT_TX | | ||
958 | AR5K_INT_FATAL); | ||
959 | |||
960 | /* | ||
961 | * Set RF kill flags if supported by the device (read from the EEPROM) | ||
962 | * Disable gpio_intr for now since it results system hang. | ||
963 | * TODO: Handle this in ath5k_intr | ||
964 | */ | ||
965 | #if 0 | ||
966 | if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { | ||
967 | ath5k_hw_set_gpio_input(ah, 0); | ||
968 | ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); | ||
969 | if (ah->ah_gpio[0] == 0) | ||
970 | ath5k_hw_set_gpio_intr(ah, 0, 1); | ||
971 | else | ||
972 | ath5k_hw_set_gpio_intr(ah, 0, 0); | ||
973 | } | ||
974 | #endif | ||
975 | |||
976 | /* | ||
977 | * Set the 32MHz reference clock on 5212 phy clock sleep register | ||
978 | */ | ||
979 | if (ah->ah_version == AR5K_AR5212) { | ||
980 | ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); | ||
981 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
982 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); | ||
983 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
984 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
985 | ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ? | ||
986 | AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112, | ||
987 | AR5K_PHY_SPENDING); | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * Disable beacons and reset the register | ||
992 | */ | ||
993 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | | ||
994 | AR5K_BEACON_RESET_TSF); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | /* | ||
1000 | * Reset chipset | ||
1001 | */ | ||
1002 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | ||
1003 | { | ||
1004 | int ret; | ||
1005 | u32 mask = val ? val : ~0U; | ||
1006 | |||
1007 | ATH5K_TRACE(ah->ah_sc); | ||
1008 | |||
1009 | /* Read-and-clear RX Descriptor Pointer*/ | ||
1010 | ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
1011 | |||
1012 | /* | ||
1013 | * Reset the device and wait until success | ||
1014 | */ | ||
1015 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); | ||
1016 | |||
1017 | /* Wait at least 128 PCI clocks */ | ||
1018 | udelay(15); | ||
1019 | |||
1020 | if (ah->ah_version == AR5K_AR5210) { | ||
1021 | val &= AR5K_RESET_CTL_CHIP; | ||
1022 | mask &= AR5K_RESET_CTL_CHIP; | ||
1023 | } else { | ||
1024 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
1025 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | ||
1026 | } | ||
1027 | |||
1028 | ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); | ||
1029 | |||
1030 | /* | ||
1031 | * Reset configuration register (for hw byte-swap). Note that this | ||
1032 | * is only set for big endian. We do the necessary magic in | ||
1033 | * AR5K_INIT_CFG. | ||
1034 | */ | ||
1035 | if ((val & AR5K_RESET_CTL_PCU) == 0) | ||
1036 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | ||
1037 | |||
1038 | return ret; | ||
1039 | } | ||
1040 | |||
1041 | /* | ||
1042 | * Power management functions | ||
1043 | */ | ||
1044 | |||
1045 | /* | ||
1046 | * Sleep control | ||
1047 | */ | ||
1048 | int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | ||
1049 | bool set_chip, u16 sleep_duration) | ||
1050 | { | ||
1051 | unsigned int i; | ||
1052 | u32 staid; | ||
1053 | |||
1054 | ATH5K_TRACE(ah->ah_sc); | ||
1055 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); | ||
1056 | |||
1057 | switch (mode) { | ||
1058 | case AR5K_PM_AUTO: | ||
1059 | staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; | ||
1060 | /* fallthrough */ | ||
1061 | case AR5K_PM_NETWORK_SLEEP: | ||
1062 | if (set_chip == true) | ||
1063 | ath5k_hw_reg_write(ah, | ||
1064 | AR5K_SLEEP_CTL_SLE | sleep_duration, | ||
1065 | AR5K_SLEEP_CTL); | ||
1066 | |||
1067 | staid |= AR5K_STA_ID1_PWR_SV; | ||
1068 | break; | ||
1069 | |||
1070 | case AR5K_PM_FULL_SLEEP: | ||
1071 | if (set_chip == true) | ||
1072 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, | ||
1073 | AR5K_SLEEP_CTL); | ||
1074 | |||
1075 | staid |= AR5K_STA_ID1_PWR_SV; | ||
1076 | break; | ||
1077 | |||
1078 | case AR5K_PM_AWAKE: | ||
1079 | if (set_chip == false) | ||
1080 | goto commit; | ||
1081 | |||
1082 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, | ||
1083 | AR5K_SLEEP_CTL); | ||
1084 | |||
1085 | for (i = 5000; i > 0; i--) { | ||
1086 | /* Check if the chip did wake up */ | ||
1087 | if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & | ||
1088 | AR5K_PCICFG_SPWR_DN) == 0) | ||
1089 | break; | ||
1090 | |||
1091 | /* Wait a bit and retry */ | ||
1092 | udelay(200); | ||
1093 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, | ||
1094 | AR5K_SLEEP_CTL); | ||
1095 | } | ||
1096 | |||
1097 | /* Fail if the chip didn't wake up */ | ||
1098 | if (i <= 0) | ||
1099 | return -EIO; | ||
1100 | |||
1101 | staid &= ~AR5K_STA_ID1_PWR_SV; | ||
1102 | break; | ||
1103 | |||
1104 | default: | ||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | |||
1108 | commit: | ||
1109 | ah->ah_power_mode = mode; | ||
1110 | ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); | ||
1111 | |||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | /***********************\ | ||
1116 | DMA Related Functions | ||
1117 | \***********************/ | ||
1118 | |||
1119 | /* | ||
1120 | * Receive functions | ||
1121 | */ | ||
1122 | |||
1123 | /* | ||
1124 | * Start DMA receive | ||
1125 | */ | ||
1126 | void ath5k_hw_start_rx(struct ath5k_hw *ah) | ||
1127 | { | ||
1128 | ATH5K_TRACE(ah->ah_sc); | ||
1129 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); | ||
1130 | } | ||
1131 | |||
1132 | /* | ||
1133 | * Stop DMA receive | ||
1134 | */ | ||
1135 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | ||
1136 | { | ||
1137 | unsigned int i; | ||
1138 | |||
1139 | ATH5K_TRACE(ah->ah_sc); | ||
1140 | ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); | ||
1141 | |||
1142 | /* | ||
1143 | * It may take some time to disable the DMA receive unit | ||
1144 | */ | ||
1145 | for (i = 2000; i > 0 && | ||
1146 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; | ||
1147 | i--) | ||
1148 | udelay(10); | ||
1149 | |||
1150 | return i ? 0 : -EBUSY; | ||
1151 | } | ||
1152 | |||
1153 | /* | ||
1154 | * Get the address of the RX Descriptor | ||
1155 | */ | ||
1156 | u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah) | ||
1157 | { | ||
1158 | return ath5k_hw_reg_read(ah, AR5K_RXDP); | ||
1159 | } | ||
1160 | |||
1161 | /* | ||
1162 | * Set the address of the RX Descriptor | ||
1163 | */ | ||
1164 | void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr) | ||
1165 | { | ||
1166 | ATH5K_TRACE(ah->ah_sc); | ||
1167 | |||
1168 | /*TODO:Shouldn't we check if RX is enabled first ?*/ | ||
1169 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); | ||
1170 | } | ||
1171 | |||
1172 | /* | ||
1173 | * Transmit functions | ||
1174 | */ | ||
1175 | |||
1176 | /* | ||
1177 | * Start DMA transmit for a specific queue | ||
1178 | * (see also QCU/DCU functions) | ||
1179 | */ | ||
1180 | int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue) | ||
1181 | { | ||
1182 | u32 tx_queue; | ||
1183 | |||
1184 | ATH5K_TRACE(ah->ah_sc); | ||
1185 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1186 | |||
1187 | /* Return if queue is declared inactive */ | ||
1188 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
1189 | return -EIO; | ||
1190 | |||
1191 | if (ah->ah_version == AR5K_AR5210) { | ||
1192 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
1193 | |||
1194 | /* | ||
1195 | * Set the queue by type on 5210 | ||
1196 | */ | ||
1197 | switch (ah->ah_txq[queue].tqi_type) { | ||
1198 | case AR5K_TX_QUEUE_DATA: | ||
1199 | tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; | ||
1200 | break; | ||
1201 | case AR5K_TX_QUEUE_BEACON: | ||
1202 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
1203 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
1204 | AR5K_BSR); | ||
1205 | break; | ||
1206 | case AR5K_TX_QUEUE_CAB: | ||
1207 | tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; | ||
1208 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | | ||
1209 | AR5K_BCR_BDMAE, AR5K_BSR); | ||
1210 | break; | ||
1211 | default: | ||
1212 | return -EINVAL; | ||
1213 | } | ||
1214 | /* Start queue */ | ||
1215 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
1216 | } else { | ||
1217 | /* Return if queue is disabled */ | ||
1218 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) | ||
1219 | return -EIO; | ||
1220 | |||
1221 | /* Start queue */ | ||
1222 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); | ||
1223 | } | ||
1224 | |||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1228 | /* | ||
1229 | * Stop DMA transmit for a specific queue | ||
1230 | * (see also QCU/DCU functions) | ||
1231 | */ | ||
1232 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | ||
1233 | { | ||
1234 | unsigned int i = 100; | ||
1235 | u32 tx_queue, pending; | ||
1236 | |||
1237 | ATH5K_TRACE(ah->ah_sc); | ||
1238 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1239 | |||
1240 | /* Return if queue is declared inactive */ | ||
1241 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
1242 | return -EIO; | ||
1243 | |||
1244 | if (ah->ah_version == AR5K_AR5210) { | ||
1245 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | ||
1246 | |||
1247 | /* | ||
1248 | * Set by queue type | ||
1249 | */ | ||
1250 | switch (ah->ah_txq[queue].tqi_type) { | ||
1251 | case AR5K_TX_QUEUE_DATA: | ||
1252 | tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; | ||
1253 | break; | ||
1254 | case AR5K_TX_QUEUE_BEACON: | ||
1255 | case AR5K_TX_QUEUE_CAB: | ||
1256 | /* XXX Fix me... */ | ||
1257 | tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; | ||
1258 | ath5k_hw_reg_write(ah, 0, AR5K_BSR); | ||
1259 | break; | ||
1260 | default: | ||
1261 | return -EINVAL; | ||
1262 | } | ||
1263 | |||
1264 | /* Stop queue */ | ||
1265 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | ||
1266 | } else { | ||
1267 | /* | ||
1268 | * Schedule TX disable and wait until queue is empty | ||
1269 | */ | ||
1270 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); | ||
1271 | |||
1272 | /*Check for pending frames*/ | ||
1273 | do { | ||
1274 | pending = ath5k_hw_reg_read(ah, | ||
1275 | AR5K_QUEUE_STATUS(queue)) & | ||
1276 | AR5K_QCU_STS_FRMPENDCNT; | ||
1277 | udelay(100); | ||
1278 | } while (--i && pending); | ||
1279 | |||
1280 | /* Clear register */ | ||
1281 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); | ||
1282 | } | ||
1283 | |||
1284 | /* TODO: Check for success else return error */ | ||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1288 | /* | ||
1289 | * Get the address of the TX Descriptor for a specific queue | ||
1290 | * (see also QCU/DCU functions) | ||
1291 | */ | ||
1292 | u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue) | ||
1293 | { | ||
1294 | u16 tx_reg; | ||
1295 | |||
1296 | ATH5K_TRACE(ah->ah_sc); | ||
1297 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1298 | |||
1299 | /* | ||
1300 | * Get the transmit queue descriptor pointer from the selected queue | ||
1301 | */ | ||
1302 | /*5210 doesn't have QCU*/ | ||
1303 | if (ah->ah_version == AR5K_AR5210) { | ||
1304 | switch (ah->ah_txq[queue].tqi_type) { | ||
1305 | case AR5K_TX_QUEUE_DATA: | ||
1306 | tx_reg = AR5K_NOQCU_TXDP0; | ||
1307 | break; | ||
1308 | case AR5K_TX_QUEUE_BEACON: | ||
1309 | case AR5K_TX_QUEUE_CAB: | ||
1310 | tx_reg = AR5K_NOQCU_TXDP1; | ||
1311 | break; | ||
1312 | default: | ||
1313 | return 0xffffffff; | ||
1314 | } | ||
1315 | } else { | ||
1316 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
1317 | } | ||
1318 | |||
1319 | return ath5k_hw_reg_read(ah, tx_reg); | ||
1320 | } | ||
1321 | |||
1322 | /* | ||
1323 | * Set the address of the TX Descriptor for a specific queue | ||
1324 | * (see also QCU/DCU functions) | ||
1325 | */ | ||
1326 | int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | ||
1327 | { | ||
1328 | u16 tx_reg; | ||
1329 | |||
1330 | ATH5K_TRACE(ah->ah_sc); | ||
1331 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
1332 | |||
1333 | /* | ||
1334 | * Set the transmit queue descriptor pointer register by type | ||
1335 | * on 5210 | ||
1336 | */ | ||
1337 | if (ah->ah_version == AR5K_AR5210) { | ||
1338 | switch (ah->ah_txq[queue].tqi_type) { | ||
1339 | case AR5K_TX_QUEUE_DATA: | ||
1340 | tx_reg = AR5K_NOQCU_TXDP0; | ||
1341 | break; | ||
1342 | case AR5K_TX_QUEUE_BEACON: | ||
1343 | case AR5K_TX_QUEUE_CAB: | ||
1344 | tx_reg = AR5K_NOQCU_TXDP1; | ||
1345 | break; | ||
1346 | default: | ||
1347 | return -EINVAL; | ||
1348 | } | ||
1349 | } else { | ||
1350 | /* | ||
1351 | * Set the transmit queue descriptor pointer for | ||
1352 | * the selected queue on QCU for 5211+ | ||
1353 | * (this won't work if the queue is still active) | ||
1354 | */ | ||
1355 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
1356 | return -EIO; | ||
1357 | |||
1358 | tx_reg = AR5K_QUEUE_TXDP(queue); | ||
1359 | } | ||
1360 | |||
1361 | /* Set descriptor pointer */ | ||
1362 | ath5k_hw_reg_write(ah, phys_addr, tx_reg); | ||
1363 | |||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1367 | /* | ||
1368 | * Update tx trigger level | ||
1369 | */ | ||
1370 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | ||
1371 | { | ||
1372 | u32 trigger_level, imr; | ||
1373 | int ret = -EIO; | ||
1374 | |||
1375 | ATH5K_TRACE(ah->ah_sc); | ||
1376 | |||
1377 | /* | ||
1378 | * Disable interrupts by setting the mask | ||
1379 | */ | ||
1380 | imr = ath5k_hw_set_intr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); | ||
1381 | |||
1382 | /*TODO: Boundary check on trigger_level*/ | ||
1383 | trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), | ||
1384 | AR5K_TXCFG_TXFULL); | ||
1385 | |||
1386 | if (increase == false) { | ||
1387 | if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) | ||
1388 | goto done; | ||
1389 | } else | ||
1390 | trigger_level += | ||
1391 | ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); | ||
1392 | |||
1393 | /* | ||
1394 | * Update trigger level on success | ||
1395 | */ | ||
1396 | if (ah->ah_version == AR5K_AR5210) | ||
1397 | ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); | ||
1398 | else | ||
1399 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
1400 | AR5K_TXCFG_TXFULL, trigger_level); | ||
1401 | |||
1402 | ret = 0; | ||
1403 | |||
1404 | done: | ||
1405 | /* | ||
1406 | * Restore interrupt mask | ||
1407 | */ | ||
1408 | ath5k_hw_set_intr(ah, imr); | ||
1409 | |||
1410 | return ret; | ||
1411 | } | ||
1412 | |||
1413 | /* | ||
1414 | * Interrupt handling | ||
1415 | */ | ||
1416 | |||
1417 | /* | ||
1418 | * Check if we have pending interrupts | ||
1419 | */ | ||
1420 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | ||
1421 | { | ||
1422 | ATH5K_TRACE(ah->ah_sc); | ||
1423 | return ath5k_hw_reg_read(ah, AR5K_INTPEND); | ||
1424 | } | ||
1425 | |||
1426 | /* | ||
1427 | * Get interrupt mask (ISR) | ||
1428 | */ | ||
1429 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | ||
1430 | { | ||
1431 | u32 data; | ||
1432 | |||
1433 | ATH5K_TRACE(ah->ah_sc); | ||
1434 | |||
1435 | /* | ||
1436 | * Read interrupt status from the Interrupt Status register | ||
1437 | * on 5210 | ||
1438 | */ | ||
1439 | if (ah->ah_version == AR5K_AR5210) { | ||
1440 | data = ath5k_hw_reg_read(ah, AR5K_ISR); | ||
1441 | if (unlikely(data == AR5K_INT_NOCARD)) { | ||
1442 | *interrupt_mask = data; | ||
1443 | return -ENODEV; | ||
1444 | } | ||
1445 | } else { | ||
1446 | /* | ||
1447 | * Read interrupt status from the Read-And-Clear shadow register | ||
1448 | * Note: PISR/SISR Not available on 5210 | ||
1449 | */ | ||
1450 | data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); | ||
1451 | } | ||
1452 | |||
1453 | /* | ||
1454 | * Get abstract interrupt mask (driver-compatible) | ||
1455 | */ | ||
1456 | *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; | ||
1457 | |||
1458 | if (unlikely(data == AR5K_INT_NOCARD)) | ||
1459 | return -ENODEV; | ||
1460 | |||
1461 | if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR)) | ||
1462 | *interrupt_mask |= AR5K_INT_RX; | ||
1463 | |||
1464 | if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR | ||
1465 | | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL)) | ||
1466 | *interrupt_mask |= AR5K_INT_TX; | ||
1467 | |||
1468 | if (ah->ah_version != AR5K_AR5210) { | ||
1469 | /*HIU = Host Interface Unit (PCI etc)*/ | ||
1470 | if (unlikely(data & (AR5K_ISR_HIUERR))) | ||
1471 | *interrupt_mask |= AR5K_INT_FATAL; | ||
1472 | |||
1473 | /*Beacon Not Ready*/ | ||
1474 | if (unlikely(data & (AR5K_ISR_BNR))) | ||
1475 | *interrupt_mask |= AR5K_INT_BNR; | ||
1476 | } | ||
1477 | |||
1478 | /* | ||
1479 | * XXX: BMISS interrupts may occur after association. | ||
1480 | * I found this on 5210 code but it needs testing. If this is | ||
1481 | * true we should disable them before assoc and re-enable them | ||
1482 | * after a successfull assoc + some jiffies. | ||
1483 | */ | ||
1484 | #if 0 | ||
1485 | interrupt_mask &= ~AR5K_INT_BMISS; | ||
1486 | #endif | ||
1487 | |||
1488 | /* | ||
1489 | * In case we didn't handle anything, | ||
1490 | * print the register value. | ||
1491 | */ | ||
1492 | if (unlikely(*interrupt_mask == 0 && net_ratelimit())) | ||
1493 | ATH5K_PRINTF("0x%08x\n", data); | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | /* | ||
1499 | * Set interrupt mask | ||
1500 | */ | ||
1501 | enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) | ||
1502 | { | ||
1503 | enum ath5k_int old_mask, int_mask; | ||
1504 | |||
1505 | /* | ||
1506 | * Disable card interrupts to prevent any race conditions | ||
1507 | * (they will be re-enabled afterwards). | ||
1508 | */ | ||
1509 | ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); | ||
1510 | |||
1511 | old_mask = ah->ah_imr; | ||
1512 | |||
1513 | /* | ||
1514 | * Add additional, chipset-dependent interrupt mask flags | ||
1515 | * and write them to the IMR (interrupt mask register). | ||
1516 | */ | ||
1517 | int_mask = new_mask & AR5K_INT_COMMON; | ||
1518 | |||
1519 | if (new_mask & AR5K_INT_RX) | ||
1520 | int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN | | ||
1521 | AR5K_IMR_RXDESC; | ||
1522 | |||
1523 | if (new_mask & AR5K_INT_TX) | ||
1524 | int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC | | ||
1525 | AR5K_IMR_TXURN; | ||
1526 | |||
1527 | if (ah->ah_version != AR5K_AR5210) { | ||
1528 | if (new_mask & AR5K_INT_FATAL) { | ||
1529 | int_mask |= AR5K_IMR_HIUERR; | ||
1530 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT | | ||
1531 | AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR); | ||
1532 | } | ||
1533 | } | ||
1534 | |||
1535 | ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); | ||
1536 | |||
1537 | /* Store new interrupt mask */ | ||
1538 | ah->ah_imr = new_mask; | ||
1539 | |||
1540 | /* ..re-enable interrupts */ | ||
1541 | ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); | ||
1542 | |||
1543 | return old_mask; | ||
1544 | } | ||
1545 | |||
1546 | |||
1547 | /*************************\ | ||
1548 | EEPROM access functions | ||
1549 | \*************************/ | ||
1550 | |||
1551 | /* | ||
1552 | * Read from eeprom | ||
1553 | */ | ||
1554 | static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | ||
1555 | { | ||
1556 | u32 status, timeout; | ||
1557 | |||
1558 | ATH5K_TRACE(ah->ah_sc); | ||
1559 | /* | ||
1560 | * Initialize EEPROM access | ||
1561 | */ | ||
1562 | if (ah->ah_version == AR5K_AR5210) { | ||
1563 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
1564 | (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); | ||
1565 | } else { | ||
1566 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
1567 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1568 | AR5K_EEPROM_CMD_READ); | ||
1569 | } | ||
1570 | |||
1571 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
1572 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
1573 | if (status & AR5K_EEPROM_STAT_RDDONE) { | ||
1574 | if (status & AR5K_EEPROM_STAT_RDERR) | ||
1575 | return -EIO; | ||
1576 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | ||
1577 | 0xffff); | ||
1578 | return 0; | ||
1579 | } | ||
1580 | udelay(15); | ||
1581 | } | ||
1582 | |||
1583 | return -ETIMEDOUT; | ||
1584 | } | ||
1585 | |||
1586 | /* | ||
1587 | * Write to eeprom - currently disabled, use at your own risk | ||
1588 | */ | ||
1589 | static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data) | ||
1590 | { | ||
1591 | #if 0 | ||
1592 | u32 status, timeout; | ||
1593 | |||
1594 | ATH5K_TRACE(ah->ah_sc); | ||
1595 | |||
1596 | /* | ||
1597 | * Initialize eeprom access | ||
1598 | */ | ||
1599 | |||
1600 | if (ah->ah_version == AR5K_AR5210) { | ||
1601 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
1602 | } else { | ||
1603 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1604 | AR5K_EEPROM_CMD_RESET); | ||
1605 | } | ||
1606 | |||
1607 | /* | ||
1608 | * Write data to data register | ||
1609 | */ | ||
1610 | |||
1611 | if (ah->ah_version == AR5K_AR5210) { | ||
1612 | ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset)); | ||
1613 | } else { | ||
1614 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
1615 | ath5k_hw_reg_write(ah, data, AR5K_EEPROM_DATA); | ||
1616 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
1617 | AR5K_EEPROM_CMD_WRITE); | ||
1618 | } | ||
1619 | |||
1620 | /* | ||
1621 | * Check status | ||
1622 | */ | ||
1623 | |||
1624 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
1625 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
1626 | if (status & AR5K_EEPROM_STAT_WRDONE) { | ||
1627 | if (status & AR5K_EEPROM_STAT_WRERR) | ||
1628 | return EIO; | ||
1629 | return 0; | ||
1630 | } | ||
1631 | udelay(15); | ||
1632 | } | ||
1633 | #endif | ||
1634 | ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!"); | ||
1635 | return -EIO; | ||
1636 | } | ||
1637 | |||
1638 | /* | ||
1639 | * Translate binary channel representation in EEPROM to frequency | ||
1640 | */ | ||
1641 | static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, unsigned int mode) | ||
1642 | { | ||
1643 | u16 val; | ||
1644 | |||
1645 | if (bin == AR5K_EEPROM_CHANNEL_DIS) | ||
1646 | return bin; | ||
1647 | |||
1648 | if (mode == AR5K_EEPROM_MODE_11A) { | ||
1649 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
1650 | val = (5 * bin) + 4800; | ||
1651 | else | ||
1652 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | ||
1653 | (bin * 10) + 5100; | ||
1654 | } else { | ||
1655 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | ||
1656 | val = bin + 2300; | ||
1657 | else | ||
1658 | val = bin + 2400; | ||
1659 | } | ||
1660 | |||
1661 | return val; | ||
1662 | } | ||
1663 | |||
1664 | /* | ||
1665 | * Read antenna infos from eeprom | ||
1666 | */ | ||
1667 | static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | ||
1668 | unsigned int mode) | ||
1669 | { | ||
1670 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1671 | u32 o = *offset; | ||
1672 | u16 val; | ||
1673 | int ret, i = 0; | ||
1674 | |||
1675 | AR5K_EEPROM_READ(o++, val); | ||
1676 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | ||
1677 | ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f; | ||
1678 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
1679 | |||
1680 | AR5K_EEPROM_READ(o++, val); | ||
1681 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
1682 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
1683 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
1684 | |||
1685 | AR5K_EEPROM_READ(o++, val); | ||
1686 | ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; | ||
1687 | ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; | ||
1688 | ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; | ||
1689 | |||
1690 | AR5K_EEPROM_READ(o++, val); | ||
1691 | ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; | ||
1692 | ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; | ||
1693 | ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; | ||
1694 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | ||
1695 | |||
1696 | AR5K_EEPROM_READ(o++, val); | ||
1697 | ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; | ||
1698 | ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; | ||
1699 | ee->ee_ant_control[mode][i++] = val & 0x3f; | ||
1700 | |||
1701 | /* Get antenna modes */ | ||
1702 | ah->ah_antenna[mode][0] = | ||
1703 | (ee->ee_ant_control[mode][0] << 4) | 0x1; | ||
1704 | ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = | ||
1705 | ee->ee_ant_control[mode][1] | | ||
1706 | (ee->ee_ant_control[mode][2] << 6) | | ||
1707 | (ee->ee_ant_control[mode][3] << 12) | | ||
1708 | (ee->ee_ant_control[mode][4] << 18) | | ||
1709 | (ee->ee_ant_control[mode][5] << 24); | ||
1710 | ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = | ||
1711 | ee->ee_ant_control[mode][6] | | ||
1712 | (ee->ee_ant_control[mode][7] << 6) | | ||
1713 | (ee->ee_ant_control[mode][8] << 12) | | ||
1714 | (ee->ee_ant_control[mode][9] << 18) | | ||
1715 | (ee->ee_ant_control[mode][10] << 24); | ||
1716 | |||
1717 | /* return new offset */ | ||
1718 | *offset = o; | ||
1719 | |||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | /* | ||
1724 | * Read supported modes from eeprom | ||
1725 | */ | ||
1726 | static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | ||
1727 | unsigned int mode) | ||
1728 | { | ||
1729 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1730 | u32 o = *offset; | ||
1731 | u16 val; | ||
1732 | int ret; | ||
1733 | |||
1734 | AR5K_EEPROM_READ(o++, val); | ||
1735 | ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; | ||
1736 | ee->ee_thr_62[mode] = val & 0xff; | ||
1737 | |||
1738 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
1739 | ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; | ||
1740 | |||
1741 | AR5K_EEPROM_READ(o++, val); | ||
1742 | ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; | ||
1743 | ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; | ||
1744 | |||
1745 | AR5K_EEPROM_READ(o++, val); | ||
1746 | ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; | ||
1747 | |||
1748 | if ((val & 0xff) & 0x80) | ||
1749 | ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); | ||
1750 | else | ||
1751 | ee->ee_noise_floor_thr[mode] = val & 0xff; | ||
1752 | |||
1753 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) | ||
1754 | ee->ee_noise_floor_thr[mode] = | ||
1755 | mode == AR5K_EEPROM_MODE_11A ? -54 : -1; | ||
1756 | |||
1757 | AR5K_EEPROM_READ(o++, val); | ||
1758 | ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; | ||
1759 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; | ||
1760 | ee->ee_xpd[mode] = val & 0x1; | ||
1761 | |||
1762 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) | ||
1763 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; | ||
1764 | |||
1765 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { | ||
1766 | AR5K_EEPROM_READ(o++, val); | ||
1767 | ee->ee_false_detect[mode] = (val >> 6) & 0x7f; | ||
1768 | |||
1769 | if (mode == AR5K_EEPROM_MODE_11A) | ||
1770 | ee->ee_xr_power[mode] = val & 0x3f; | ||
1771 | else { | ||
1772 | ee->ee_ob[mode][0] = val & 0x7; | ||
1773 | ee->ee_db[mode][0] = (val >> 3) & 0x7; | ||
1774 | } | ||
1775 | } | ||
1776 | |||
1777 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { | ||
1778 | ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; | ||
1779 | ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; | ||
1780 | } else { | ||
1781 | ee->ee_i_gain[mode] = (val >> 13) & 0x7; | ||
1782 | |||
1783 | AR5K_EEPROM_READ(o++, val); | ||
1784 | ee->ee_i_gain[mode] |= (val << 3) & 0x38; | ||
1785 | |||
1786 | if (mode == AR5K_EEPROM_MODE_11G) | ||
1787 | ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; | ||
1788 | } | ||
1789 | |||
1790 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && | ||
1791 | mode == AR5K_EEPROM_MODE_11A) { | ||
1792 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
1793 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
1794 | } | ||
1795 | |||
1796 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 && | ||
1797 | mode == AR5K_EEPROM_MODE_11G) | ||
1798 | ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; | ||
1799 | |||
1800 | /* return new offset */ | ||
1801 | *offset = o; | ||
1802 | |||
1803 | return 0; | ||
1804 | } | ||
1805 | |||
1806 | /* | ||
1807 | * Initialize eeprom & capabilities structs | ||
1808 | */ | ||
1809 | static int ath5k_eeprom_init(struct ath5k_hw *ah) | ||
1810 | { | ||
1811 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1812 | unsigned int mode, i; | ||
1813 | int ret; | ||
1814 | u32 offset; | ||
1815 | u16 val; | ||
1816 | |||
1817 | /* Initial TX thermal adjustment values */ | ||
1818 | ee->ee_tx_clip = 4; | ||
1819 | ee->ee_pwd_84 = ee->ee_pwd_90 = 1; | ||
1820 | ee->ee_gain_select = 1; | ||
1821 | |||
1822 | /* | ||
1823 | * Read values from EEPROM and store them in the capability structure | ||
1824 | */ | ||
1825 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); | ||
1826 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); | ||
1827 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); | ||
1828 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); | ||
1829 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); | ||
1830 | |||
1831 | /* Return if we have an old EEPROM */ | ||
1832 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | ||
1833 | return 0; | ||
1834 | |||
1835 | #ifdef notyet | ||
1836 | /* | ||
1837 | * Validate the checksum of the EEPROM date. There are some | ||
1838 | * devices with invalid EEPROMs. | ||
1839 | */ | ||
1840 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | ||
1841 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | ||
1842 | cksum ^= val; | ||
1843 | } | ||
1844 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | ||
1845 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | ||
1846 | return -EIO; | ||
1847 | } | ||
1848 | #endif | ||
1849 | |||
1850 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | ||
1851 | ee_ant_gain); | ||
1852 | |||
1853 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
1854 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | ||
1855 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | ||
1856 | } | ||
1857 | |||
1858 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | ||
1859 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); | ||
1860 | ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; | ||
1861 | ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; | ||
1862 | |||
1863 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); | ||
1864 | ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; | ||
1865 | ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; | ||
1866 | } | ||
1867 | |||
1868 | /* | ||
1869 | * Get conformance test limit values | ||
1870 | */ | ||
1871 | offset = AR5K_EEPROM_CTL(ah->ah_ee_version); | ||
1872 | ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version); | ||
1873 | |||
1874 | for (i = 0; i < ee->ee_ctls; i++) { | ||
1875 | AR5K_EEPROM_READ(offset++, val); | ||
1876 | ee->ee_ctl[i] = (val >> 8) & 0xff; | ||
1877 | ee->ee_ctl[i + 1] = val & 0xff; | ||
1878 | } | ||
1879 | |||
1880 | /* | ||
1881 | * Get values for 802.11a (5GHz) | ||
1882 | */ | ||
1883 | mode = AR5K_EEPROM_MODE_11A; | ||
1884 | |||
1885 | ee->ee_turbo_max_power[mode] = | ||
1886 | AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); | ||
1887 | |||
1888 | offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); | ||
1889 | |||
1890 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
1891 | if (ret) | ||
1892 | return ret; | ||
1893 | |||
1894 | AR5K_EEPROM_READ(offset++, val); | ||
1895 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
1896 | ee->ee_ob[mode][3] = (val >> 5) & 0x7; | ||
1897 | ee->ee_db[mode][3] = (val >> 2) & 0x7; | ||
1898 | ee->ee_ob[mode][2] = (val << 1) & 0x7; | ||
1899 | |||
1900 | AR5K_EEPROM_READ(offset++, val); | ||
1901 | ee->ee_ob[mode][2] |= (val >> 15) & 0x1; | ||
1902 | ee->ee_db[mode][2] = (val >> 12) & 0x7; | ||
1903 | ee->ee_ob[mode][1] = (val >> 9) & 0x7; | ||
1904 | ee->ee_db[mode][1] = (val >> 6) & 0x7; | ||
1905 | ee->ee_ob[mode][0] = (val >> 3) & 0x7; | ||
1906 | ee->ee_db[mode][0] = val & 0x7; | ||
1907 | |||
1908 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
1909 | if (ret) | ||
1910 | return ret; | ||
1911 | |||
1912 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) { | ||
1913 | AR5K_EEPROM_READ(offset++, val); | ||
1914 | ee->ee_margin_tx_rx[mode] = val & 0x3f; | ||
1915 | } | ||
1916 | |||
1917 | /* | ||
1918 | * Get values for 802.11b (2.4GHz) | ||
1919 | */ | ||
1920 | mode = AR5K_EEPROM_MODE_11B; | ||
1921 | offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); | ||
1922 | |||
1923 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
1924 | if (ret) | ||
1925 | return ret; | ||
1926 | |||
1927 | AR5K_EEPROM_READ(offset++, val); | ||
1928 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
1929 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
1930 | ee->ee_db[mode][1] = val & 0x7; | ||
1931 | |||
1932 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
1933 | if (ret) | ||
1934 | return ret; | ||
1935 | |||
1936 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
1937 | AR5K_EEPROM_READ(offset++, val); | ||
1938 | ee->ee_cal_pier[mode][0] = | ||
1939 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
1940 | ee->ee_cal_pier[mode][1] = | ||
1941 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
1942 | |||
1943 | AR5K_EEPROM_READ(offset++, val); | ||
1944 | ee->ee_cal_pier[mode][2] = | ||
1945 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
1946 | } | ||
1947 | |||
1948 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
1949 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
1950 | |||
1951 | /* | ||
1952 | * Get values for 802.11g (2.4GHz) | ||
1953 | */ | ||
1954 | mode = AR5K_EEPROM_MODE_11G; | ||
1955 | offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); | ||
1956 | |||
1957 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
1958 | if (ret) | ||
1959 | return ret; | ||
1960 | |||
1961 | AR5K_EEPROM_READ(offset++, val); | ||
1962 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
1963 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
1964 | ee->ee_db[mode][1] = val & 0x7; | ||
1965 | |||
1966 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
1967 | if (ret) | ||
1968 | return ret; | ||
1969 | |||
1970 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
1971 | AR5K_EEPROM_READ(offset++, val); | ||
1972 | ee->ee_cal_pier[mode][0] = | ||
1973 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
1974 | ee->ee_cal_pier[mode][1] = | ||
1975 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
1976 | |||
1977 | AR5K_EEPROM_READ(offset++, val); | ||
1978 | ee->ee_turbo_max_power[mode] = val & 0x7f; | ||
1979 | ee->ee_xr_power[mode] = (val >> 7) & 0x3f; | ||
1980 | |||
1981 | AR5K_EEPROM_READ(offset++, val); | ||
1982 | ee->ee_cal_pier[mode][2] = | ||
1983 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | ||
1984 | |||
1985 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
1986 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
1987 | |||
1988 | AR5K_EEPROM_READ(offset++, val); | ||
1989 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
1990 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
1991 | |||
1992 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | ||
1993 | AR5K_EEPROM_READ(offset++, val); | ||
1994 | ee->ee_cck_ofdm_gain_delta = val & 0xff; | ||
1995 | } | ||
1996 | } | ||
1997 | |||
1998 | /* | ||
1999 | * Read 5GHz EEPROM channels | ||
2000 | */ | ||
2001 | |||
2002 | return 0; | ||
2003 | } | ||
2004 | |||
2005 | /* | ||
2006 | * Read the MAC address from eeprom | ||
2007 | */ | ||
2008 | static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
2009 | { | ||
2010 | u8 mac_d[ETH_ALEN]; | ||
2011 | u32 total, offset; | ||
2012 | u16 data; | ||
2013 | int octet, ret; | ||
2014 | |||
2015 | memset(mac, 0, ETH_ALEN); | ||
2016 | memset(mac_d, 0, ETH_ALEN); | ||
2017 | |||
2018 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
2019 | if (ret) | ||
2020 | return ret; | ||
2021 | |||
2022 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
2023 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | ||
2024 | if (ret) | ||
2025 | return ret; | ||
2026 | |||
2027 | total += data; | ||
2028 | mac_d[octet + 1] = data & 0xff; | ||
2029 | mac_d[octet] = data >> 8; | ||
2030 | octet += 2; | ||
2031 | } | ||
2032 | |||
2033 | memcpy(mac, mac_d, ETH_ALEN); | ||
2034 | |||
2035 | if (!total || total == 3 * 0xffff) | ||
2036 | return -EINVAL; | ||
2037 | |||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2041 | /* | ||
2042 | * Read/Write regulatory domain | ||
2043 | */ | ||
2044 | static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write, | ||
2045 | enum ath5k_regdom *regdomain) | ||
2046 | { | ||
2047 | u16 ee_regdomain; | ||
2048 | |||
2049 | /* Read current value */ | ||
2050 | if (write != true) { | ||
2051 | ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain; | ||
2052 | *regdomain = ath5k_regdom_to_ieee(ee_regdomain); | ||
2053 | return true; | ||
2054 | } | ||
2055 | |||
2056 | ee_regdomain = ath5k_regdom_from_ieee(*regdomain); | ||
2057 | |||
2058 | /* Try to write a new value */ | ||
2059 | if (ah->ah_capabilities.cap_eeprom.ee_protect & | ||
2060 | AR5K_EEPROM_PROTECT_WR_128_191) | ||
2061 | return false; | ||
2062 | if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0) | ||
2063 | return false; | ||
2064 | |||
2065 | ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain; | ||
2066 | |||
2067 | return true; | ||
2068 | } | ||
2069 | |||
2070 | /* | ||
2071 | * Use the above to write a new regulatory domain | ||
2072 | */ | ||
2073 | int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain) | ||
2074 | { | ||
2075 | enum ath5k_regdom ieee_regdomain; | ||
2076 | |||
2077 | ieee_regdomain = ath5k_regdom_to_ieee(regdomain); | ||
2078 | |||
2079 | if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true) | ||
2080 | return 0; | ||
2081 | |||
2082 | return -EIO; | ||
2083 | } | ||
2084 | |||
2085 | /* | ||
2086 | * Fill the capabilities struct | ||
2087 | */ | ||
2088 | static int ath5k_hw_get_capabilities(struct ath5k_hw *ah) | ||
2089 | { | ||
2090 | u16 ee_header; | ||
2091 | |||
2092 | ATH5K_TRACE(ah->ah_sc); | ||
2093 | /* Capabilities stored in the EEPROM */ | ||
2094 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | ||
2095 | |||
2096 | if (ah->ah_version == AR5K_AR5210) { | ||
2097 | /* | ||
2098 | * Set radio capabilities | ||
2099 | * (The AR5110 only supports the middle 5GHz band) | ||
2100 | */ | ||
2101 | ah->ah_capabilities.cap_range.range_5ghz_min = 5120; | ||
2102 | ah->ah_capabilities.cap_range.range_5ghz_max = 5430; | ||
2103 | ah->ah_capabilities.cap_range.range_2ghz_min = 0; | ||
2104 | ah->ah_capabilities.cap_range.range_2ghz_max = 0; | ||
2105 | |||
2106 | /* Set supported modes */ | ||
2107 | __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode); | ||
2108 | __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode); | ||
2109 | } else { | ||
2110 | /* | ||
2111 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz | ||
2112 | * XXX and from 2312 to 2732GHz. There are problems with the | ||
2113 | * XXX current ieee80211 implementation because the IEEE | ||
2114 | * XXX channel mapping does not support negative channel | ||
2115 | * XXX numbers (2312MHz is channel -19). Of course, this | ||
2116 | * XXX doesn't matter because these channels are out of range | ||
2117 | * XXX but some regulation domains like MKK (Japan) will | ||
2118 | * XXX support frequencies somewhere around 4.8GHz. | ||
2119 | */ | ||
2120 | |||
2121 | /* | ||
2122 | * Set radio capabilities | ||
2123 | */ | ||
2124 | |||
2125 | if (AR5K_EEPROM_HDR_11A(ee_header)) { | ||
2126 | ah->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */ | ||
2127 | ah->ah_capabilities.cap_range.range_5ghz_max = 6100; | ||
2128 | |||
2129 | /* Set supported modes */ | ||
2130 | __set_bit(MODE_IEEE80211A, | ||
2131 | ah->ah_capabilities.cap_mode); | ||
2132 | __set_bit(MODE_ATHEROS_TURBO, | ||
2133 | ah->ah_capabilities.cap_mode); | ||
2134 | if (ah->ah_version == AR5K_AR5212) | ||
2135 | __set_bit(MODE_ATHEROS_TURBOG, | ||
2136 | ah->ah_capabilities.cap_mode); | ||
2137 | } | ||
2138 | |||
2139 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | ||
2140 | * connected */ | ||
2141 | if (AR5K_EEPROM_HDR_11B(ee_header) || | ||
2142 | AR5K_EEPROM_HDR_11G(ee_header)) { | ||
2143 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */ | ||
2144 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | ||
2145 | |||
2146 | if (AR5K_EEPROM_HDR_11B(ee_header)) | ||
2147 | __set_bit(MODE_IEEE80211B, | ||
2148 | ah->ah_capabilities.cap_mode); | ||
2149 | |||
2150 | if (AR5K_EEPROM_HDR_11G(ee_header)) | ||
2151 | __set_bit(MODE_IEEE80211G, | ||
2152 | ah->ah_capabilities.cap_mode); | ||
2153 | } | ||
2154 | } | ||
2155 | |||
2156 | /* GPIO */ | ||
2157 | ah->ah_gpio_npins = AR5K_NUM_GPIO; | ||
2158 | |||
2159 | /* Set number of supported TX queues */ | ||
2160 | if (ah->ah_version == AR5K_AR5210) | ||
2161 | ah->ah_capabilities.cap_queues.q_tx_num = | ||
2162 | AR5K_NUM_TX_QUEUES_NOQCU; | ||
2163 | else | ||
2164 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | ||
2165 | |||
2166 | return 0; | ||
2167 | } | ||
2168 | |||
2169 | /*********************************\ | ||
2170 | Protocol Control Unit Functions | ||
2171 | \*********************************/ | ||
2172 | |||
2173 | /* | ||
2174 | * Set Operation mode | ||
2175 | */ | ||
2176 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | ||
2177 | { | ||
2178 | u32 pcu_reg, beacon_reg, low_id, high_id; | ||
2179 | |||
2180 | pcu_reg = 0; | ||
2181 | beacon_reg = 0; | ||
2182 | |||
2183 | ATH5K_TRACE(ah->ah_sc); | ||
2184 | |||
2185 | switch (ah->ah_op_mode) { | ||
2186 | case IEEE80211_IF_TYPE_IBSS: | ||
2187 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA | | ||
2188 | (ah->ah_version == AR5K_AR5210 ? | ||
2189 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2190 | beacon_reg |= AR5K_BCR_ADHOC; | ||
2191 | break; | ||
2192 | |||
2193 | case IEEE80211_IF_TYPE_AP: | ||
2194 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA | | ||
2195 | (ah->ah_version == AR5K_AR5210 ? | ||
2196 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2197 | beacon_reg |= AR5K_BCR_AP; | ||
2198 | break; | ||
2199 | |||
2200 | case IEEE80211_IF_TYPE_STA: | ||
2201 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2202 | (ah->ah_version == AR5K_AR5210 ? | ||
2203 | AR5K_STA_ID1_PWR_SV : 0); | ||
2204 | case IEEE80211_IF_TYPE_MNTR: | ||
2205 | pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2206 | (ah->ah_version == AR5K_AR5210 ? | ||
2207 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
2208 | break; | ||
2209 | |||
2210 | default: | ||
2211 | return -EINVAL; | ||
2212 | } | ||
2213 | |||
2214 | /* | ||
2215 | * Set PCU registers | ||
2216 | */ | ||
2217 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | ||
2218 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | ||
2219 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
2220 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
2221 | |||
2222 | /* | ||
2223 | * Set Beacon Control Register on 5210 | ||
2224 | */ | ||
2225 | if (ah->ah_version == AR5K_AR5210) | ||
2226 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | ||
2227 | |||
2228 | return 0; | ||
2229 | } | ||
2230 | |||
2231 | /* | ||
2232 | * BSSID Functions | ||
2233 | */ | ||
2234 | |||
2235 | /* | ||
2236 | * Get station id | ||
2237 | */ | ||
2238 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | ||
2239 | { | ||
2240 | ATH5K_TRACE(ah->ah_sc); | ||
2241 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | ||
2242 | } | ||
2243 | |||
2244 | /* | ||
2245 | * Set station id | ||
2246 | */ | ||
2247 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | ||
2248 | { | ||
2249 | u32 low_id, high_id; | ||
2250 | |||
2251 | ATH5K_TRACE(ah->ah_sc); | ||
2252 | /* Set new station ID */ | ||
2253 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | ||
2254 | |||
2255 | low_id = AR5K_LOW_ID(mac); | ||
2256 | high_id = AR5K_HIGH_ID(mac); | ||
2257 | |||
2258 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
2259 | ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1); | ||
2260 | |||
2261 | return 0; | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * Set BSSID | ||
2266 | */ | ||
2267 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | ||
2268 | { | ||
2269 | u32 low_id, high_id; | ||
2270 | u16 tim_offset = 0; | ||
2271 | |||
2272 | /* | ||
2273 | * Set simple BSSID mask on 5212 | ||
2274 | */ | ||
2275 | if (ah->ah_version == AR5K_AR5212) { | ||
2276 | ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0); | ||
2277 | ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1); | ||
2278 | } | ||
2279 | |||
2280 | /* | ||
2281 | * Set BSSID which triggers the "SME Join" operation | ||
2282 | */ | ||
2283 | low_id = AR5K_LOW_ID(bssid); | ||
2284 | high_id = AR5K_HIGH_ID(bssid); | ||
2285 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | ||
2286 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | ||
2287 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | ||
2288 | |||
2289 | if (assoc_id == 0) { | ||
2290 | ath5k_hw_disable_pspoll(ah); | ||
2291 | return; | ||
2292 | } | ||
2293 | |||
2294 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | ||
2295 | tim_offset ? tim_offset + 4 : 0); | ||
2296 | |||
2297 | ath5k_hw_enable_pspoll(ah, NULL, 0); | ||
2298 | } | ||
2299 | /** | ||
2300 | * ath5k_hw_set_bssid_mask - set common bits we should listen to | ||
2301 | * | ||
2302 | * The bssid_mask is a utility used by AR5212 hardware to inform the hardware | ||
2303 | * which bits of the interface's MAC address should be looked at when trying | ||
2304 | * to decide which packets to ACK. In station mode every bit matters. In AP | ||
2305 | * mode with a single BSS every bit matters as well. In AP mode with | ||
2306 | * multiple BSSes not every bit matters. | ||
2307 | * | ||
2308 | * @ah: the &struct ath5k_hw | ||
2309 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | ||
2310 | * | ||
2311 | * Note that this is a simple filter and *does* not filter out all | ||
2312 | * relevant frames. Some non-relevant frames will get through, probability | ||
2313 | * jocks are welcomed to compute. | ||
2314 | * | ||
2315 | * When handling multiple BSSes (or VAPs) you can get the BSSID mask by | ||
2316 | * computing the set of: | ||
2317 | * | ||
2318 | * ~ ( MAC XOR BSSID ) | ||
2319 | * | ||
2320 | * When you do this you are essentially computing the common bits. Later it | ||
2321 | * is assumed the harware will "and" (&) the BSSID mask with the MAC address | ||
2322 | * to obtain the relevant bits which should match on the destination frame. | ||
2323 | * | ||
2324 | * Simple example: on your card you have have two BSSes you have created with | ||
2325 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
2326 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
2327 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
2328 | * | ||
2329 | * \ | ||
2330 | * MAC: 0001 | | ||
2331 | * BSSID-01: 0100 | --> Belongs to us | ||
2332 | * BSSID-02: 1001 | | ||
2333 | * / | ||
2334 | * ------------------- | ||
2335 | * BSSID-03: 0110 | --> External | ||
2336 | * ------------------- | ||
2337 | * | ||
2338 | * Our bssid_mask would then be: | ||
2339 | * | ||
2340 | * On loop iteration for BSSID-01: | ||
2341 | * ~(0001 ^ 0100) -> ~(0101) | ||
2342 | * -> 1010 | ||
2343 | * bssid_mask = 1010 | ||
2344 | * | ||
2345 | * On loop iteration for BSSID-02: | ||
2346 | * bssid_mask &= ~(0001 ^ 1001) | ||
2347 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
2348 | * bssid_mask = (1010) & ~(1001) | ||
2349 | * bssid_mask = (1010) & (0110) | ||
2350 | * bssid_mask = 0010 | ||
2351 | * | ||
2352 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
2353 | * significant bit". This is because its the only bit common | ||
2354 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
2355 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
2356 | * or our MAC address (we assume the hardware uses the MAC address). | ||
2357 | * | ||
2358 | * Now, suppose there's an incoming frame for BSSID-03: | ||
2359 | * | ||
2360 | * IFRAME-01: 0110 | ||
2361 | * | ||
2362 | * An easy eye-inspeciton of this already should tell you that this frame | ||
2363 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
2364 | * hardware to only look at the second least significant bit and the | ||
2365 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
2366 | * as 1, which does not match 0. | ||
2367 | * | ||
2368 | * So with IFRAME-01 we *assume* the hardware will do: | ||
2369 | * | ||
2370 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
2371 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
2372 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
2373 | * --> allow = 0 | ||
2374 | * | ||
2375 | * Lets now test a frame that should work: | ||
2376 | * | ||
2377 | * IFRAME-02: 0001 (we should allow) | ||
2378 | * | ||
2379 | * allow = (0001 & 1010) == 1010 | ||
2380 | * | ||
2381 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
2382 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
2383 | * --> allow = (0010) == (0010) | ||
2384 | * --> allow = 1 | ||
2385 | * | ||
2386 | * Other examples: | ||
2387 | * | ||
2388 | * IFRAME-03: 0100 --> allowed | ||
2389 | * IFRAME-04: 1001 --> allowed | ||
2390 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
2391 | * | ||
2392 | */ | ||
2393 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
2394 | { | ||
2395 | u32 low_id, high_id; | ||
2396 | ATH5K_TRACE(ah->ah_sc); | ||
2397 | |||
2398 | if (ah->ah_version == AR5K_AR5212) { | ||
2399 | low_id = AR5K_LOW_ID(mask); | ||
2400 | high_id = AR5K_HIGH_ID(mask); | ||
2401 | |||
2402 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | ||
2403 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | ||
2404 | |||
2405 | return 0; | ||
2406 | } | ||
2407 | |||
2408 | return -EIO; | ||
2409 | } | ||
2410 | |||
2411 | /* | ||
2412 | * Receive start/stop functions | ||
2413 | */ | ||
2414 | |||
2415 | /* | ||
2416 | * Start receive on PCU | ||
2417 | */ | ||
2418 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
2419 | { | ||
2420 | ATH5K_TRACE(ah->ah_sc); | ||
2421 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
2422 | } | ||
2423 | |||
2424 | /* | ||
2425 | * Stop receive on PCU | ||
2426 | */ | ||
2427 | void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah) | ||
2428 | { | ||
2429 | ATH5K_TRACE(ah->ah_sc); | ||
2430 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
2431 | } | ||
2432 | |||
2433 | /* | ||
2434 | * RX Filter functions | ||
2435 | */ | ||
2436 | |||
2437 | /* | ||
2438 | * Set multicast filter | ||
2439 | */ | ||
2440 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | ||
2441 | { | ||
2442 | ATH5K_TRACE(ah->ah_sc); | ||
2443 | /* Set the multicat filter */ | ||
2444 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | ||
2445 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | ||
2446 | } | ||
2447 | |||
2448 | /* | ||
2449 | * Set multicast filter by index | ||
2450 | */ | ||
2451 | int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index) | ||
2452 | { | ||
2453 | |||
2454 | ATH5K_TRACE(ah->ah_sc); | ||
2455 | if (index >= 64) | ||
2456 | return -EINVAL; | ||
2457 | else if (index >= 32) | ||
2458 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
2459 | (1 << (index - 32))); | ||
2460 | else | ||
2461 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
2462 | |||
2463 | return 0; | ||
2464 | } | ||
2465 | |||
2466 | /* | ||
2467 | * Clear Multicast filter by index | ||
2468 | */ | ||
2469 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
2470 | { | ||
2471 | |||
2472 | ATH5K_TRACE(ah->ah_sc); | ||
2473 | if (index >= 64) | ||
2474 | return -EINVAL; | ||
2475 | else if (index >= 32) | ||
2476 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
2477 | (1 << (index - 32))); | ||
2478 | else | ||
2479 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
2480 | |||
2481 | return 0; | ||
2482 | } | ||
2483 | |||
2484 | /* | ||
2485 | * Get current rx filter | ||
2486 | */ | ||
2487 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | ||
2488 | { | ||
2489 | u32 data, filter = 0; | ||
2490 | |||
2491 | ATH5K_TRACE(ah->ah_sc); | ||
2492 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); | ||
2493 | |||
2494 | /*Radar detection for 5212*/ | ||
2495 | if (ah->ah_version == AR5K_AR5212) { | ||
2496 | data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); | ||
2497 | |||
2498 | if (data & AR5K_PHY_ERR_FIL_RADAR) | ||
2499 | filter |= AR5K_RX_FILTER_RADARERR; | ||
2500 | if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) | ||
2501 | filter |= AR5K_RX_FILTER_PHYERR; | ||
2502 | } | ||
2503 | |||
2504 | return filter; | ||
2505 | } | ||
2506 | |||
2507 | /* | ||
2508 | * Set rx filter | ||
2509 | */ | ||
2510 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | ||
2511 | { | ||
2512 | u32 data = 0; | ||
2513 | |||
2514 | ATH5K_TRACE(ah->ah_sc); | ||
2515 | |||
2516 | /* Set PHY error filter register on 5212*/ | ||
2517 | if (ah->ah_version == AR5K_AR5212) { | ||
2518 | if (filter & AR5K_RX_FILTER_RADARERR) | ||
2519 | data |= AR5K_PHY_ERR_FIL_RADAR; | ||
2520 | if (filter & AR5K_RX_FILTER_PHYERR) | ||
2521 | data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; | ||
2522 | } | ||
2523 | |||
2524 | /* | ||
2525 | * The AR5210 uses promiscous mode to detect radar activity | ||
2526 | */ | ||
2527 | if (ah->ah_version == AR5K_AR5210 && | ||
2528 | (filter & AR5K_RX_FILTER_RADARERR)) { | ||
2529 | filter &= ~AR5K_RX_FILTER_RADARERR; | ||
2530 | filter |= AR5K_RX_FILTER_PROM; | ||
2531 | } | ||
2532 | |||
2533 | /*Zero length DMA*/ | ||
2534 | if (data) | ||
2535 | AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
2536 | else | ||
2537 | AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); | ||
2538 | |||
2539 | /*Write RX Filter register*/ | ||
2540 | ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); | ||
2541 | |||
2542 | /*Write PHY error filter register on 5212*/ | ||
2543 | if (ah->ah_version == AR5K_AR5212) | ||
2544 | ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); | ||
2545 | |||
2546 | } | ||
2547 | |||
2548 | /* | ||
2549 | * Beacon related functions | ||
2550 | */ | ||
2551 | |||
2552 | /* | ||
2553 | * Get a 32bit TSF | ||
2554 | */ | ||
2555 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
2556 | { | ||
2557 | ATH5K_TRACE(ah->ah_sc); | ||
2558 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
2559 | } | ||
2560 | |||
2561 | /* | ||
2562 | * Get the full 64bit TSF | ||
2563 | */ | ||
2564 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | ||
2565 | { | ||
2566 | u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
2567 | ATH5K_TRACE(ah->ah_sc); | ||
2568 | |||
2569 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); | ||
2570 | } | ||
2571 | |||
2572 | /* | ||
2573 | * Force a TSF reset | ||
2574 | */ | ||
2575 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | ||
2576 | { | ||
2577 | ATH5K_TRACE(ah->ah_sc); | ||
2578 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF); | ||
2579 | } | ||
2580 | |||
2581 | /* | ||
2582 | * Initialize beacon timers | ||
2583 | */ | ||
2584 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | ||
2585 | { | ||
2586 | u32 timer1, timer2, timer3; | ||
2587 | |||
2588 | ATH5K_TRACE(ah->ah_sc); | ||
2589 | /* | ||
2590 | * Set the additional timers by mode | ||
2591 | */ | ||
2592 | switch (ah->ah_op_mode) { | ||
2593 | case IEEE80211_IF_TYPE_STA: | ||
2594 | if (ah->ah_version == AR5K_AR5210) { | ||
2595 | timer1 = 0xffffffff; | ||
2596 | timer2 = 0xffffffff; | ||
2597 | } else { | ||
2598 | timer1 = 0x0000ffff; | ||
2599 | timer2 = 0x0007ffff; | ||
2600 | } | ||
2601 | break; | ||
2602 | |||
2603 | default: | ||
2604 | timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << | ||
2605 | 0x00000003; | ||
2606 | timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << | ||
2607 | 0x00000003; | ||
2608 | } | ||
2609 | |||
2610 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | ||
2611 | |||
2612 | /* | ||
2613 | * Set the beacon register and enable all timers. | ||
2614 | * (next beacon, DMA beacon, software beacon, ATIM window time) | ||
2615 | */ | ||
2616 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | ||
2617 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | ||
2618 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | ||
2619 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | ||
2620 | |||
2621 | ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | | ||
2622 | AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE), | ||
2623 | AR5K_BEACON); | ||
2624 | } | ||
2625 | |||
2626 | #if 0 | ||
2627 | /* | ||
2628 | * Set beacon timers | ||
2629 | */ | ||
2630 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
2631 | const struct ath5k_beacon_state *state) | ||
2632 | { | ||
2633 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
2634 | |||
2635 | /* | ||
2636 | * TODO: should be changed through *state | ||
2637 | * review struct ath5k_beacon_state struct | ||
2638 | * | ||
2639 | * XXX: These are used for cfp period bellow, are they | ||
2640 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
2641 | * get_tsf ? | ||
2642 | */ | ||
2643 | u32 dtim_count = 0; /* XXX */ | ||
2644 | u32 cfp_count = 0; /* XXX */ | ||
2645 | u32 tsf = 0; /* XXX */ | ||
2646 | |||
2647 | ATH5K_TRACE(ah->ah_sc); | ||
2648 | /* Return on an invalid beacon state */ | ||
2649 | if (state->bs_interval < 1) | ||
2650 | return -EINVAL; | ||
2651 | |||
2652 | interval = state->bs_interval; | ||
2653 | dtim = state->bs_dtim_period; | ||
2654 | |||
2655 | /* | ||
2656 | * PCF support? | ||
2657 | */ | ||
2658 | if (state->bs_cfp_period > 0) { | ||
2659 | /* | ||
2660 | * Enable PCF mode and set the CFP | ||
2661 | * (Contention Free Period) and timer registers | ||
2662 | */ | ||
2663 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
2664 | state->bs_interval; | ||
2665 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
2666 | state->bs_interval; | ||
2667 | |||
2668 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
2669 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2670 | AR5K_STA_ID1_PCF); | ||
2671 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
2672 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
2673 | AR5K_CFP_DUR); | ||
2674 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
2675 | next_cfp)) << 3, AR5K_TIMER2); | ||
2676 | } else { | ||
2677 | /* Disable PCF mode */ | ||
2678 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
2679 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
2680 | AR5K_STA_ID1_PCF); | ||
2681 | } | ||
2682 | |||
2683 | /* | ||
2684 | * Enable the beacon timer register | ||
2685 | */ | ||
2686 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
2687 | |||
2688 | /* | ||
2689 | * Start the beacon timers | ||
2690 | */ | ||
2691 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &~ | ||
2692 | (AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
2693 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
2694 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
2695 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
2696 | |||
2697 | /* | ||
2698 | * Write new beacon miss threshold, if it appears to be valid | ||
2699 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
2700 | * and return if its not in range. We can test this by reading value and | ||
2701 | * setting value to a largest value and seeing which values register. | ||
2702 | */ | ||
2703 | |||
2704 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
2705 | state->bs_bmiss_threshold); | ||
2706 | |||
2707 | /* | ||
2708 | * Set sleep control register | ||
2709 | * XXX: Didn't find this in 5210 code but since this register | ||
2710 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
2711 | */ | ||
2712 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
2713 | (state->bs_sleep_duration - 3) << 3); | ||
2714 | |||
2715 | /* | ||
2716 | * Set enhanced sleep registers on 5212 | ||
2717 | */ | ||
2718 | if (ah->ah_version == AR5K_AR5212) { | ||
2719 | if (state->bs_sleep_duration > state->bs_interval && | ||
2720 | roundup(state->bs_sleep_duration, interval) == | ||
2721 | state->bs_sleep_duration) | ||
2722 | interval = state->bs_sleep_duration; | ||
2723 | |||
2724 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
2725 | roundup(state->bs_sleep_duration, dtim) == | ||
2726 | state->bs_sleep_duration)) | ||
2727 | dtim = state->bs_sleep_duration; | ||
2728 | |||
2729 | if (interval > dtim) | ||
2730 | return -EINVAL; | ||
2731 | |||
2732 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
2733 | state->bs_next_beacon; | ||
2734 | |||
2735 | ath5k_hw_reg_write(ah, | ||
2736 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
2737 | AR5K_SLEEP0_NEXT_DTIM) | | ||
2738 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
2739 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
2740 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
2741 | |||
2742 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
2743 | AR5K_SLEEP1_NEXT_TIM) | | ||
2744 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
2745 | |||
2746 | ath5k_hw_reg_write(ah, | ||
2747 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
2748 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
2749 | } | ||
2750 | |||
2751 | return 0; | ||
2752 | } | ||
2753 | |||
2754 | /* | ||
2755 | * Reset beacon timers | ||
2756 | */ | ||
2757 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
2758 | { | ||
2759 | ATH5K_TRACE(ah->ah_sc); | ||
2760 | /* | ||
2761 | * Disable beacon timer | ||
2762 | */ | ||
2763 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
2764 | |||
2765 | /* | ||
2766 | * Disable some beacon register values | ||
2767 | */ | ||
2768 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
2769 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
2770 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
2771 | } | ||
2772 | |||
2773 | /* | ||
2774 | * Wait for beacon queue to finish | ||
2775 | */ | ||
2776 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
2777 | { | ||
2778 | unsigned int i; | ||
2779 | int ret; | ||
2780 | |||
2781 | ATH5K_TRACE(ah->ah_sc); | ||
2782 | |||
2783 | /* 5210 doesn't have QCU*/ | ||
2784 | if (ah->ah_version == AR5K_AR5210) { | ||
2785 | /* | ||
2786 | * Wait for beaconn queue to finish by checking | ||
2787 | * Control Register and Beacon Status Register. | ||
2788 | */ | ||
2789 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
2790 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
2791 | || | ||
2792 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
2793 | break; | ||
2794 | udelay(10); | ||
2795 | } | ||
2796 | |||
2797 | /* Timeout... */ | ||
2798 | if (i <= 0) { | ||
2799 | /* | ||
2800 | * Re-schedule the beacon queue | ||
2801 | */ | ||
2802 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
2803 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
2804 | AR5K_BCR); | ||
2805 | |||
2806 | return -EIO; | ||
2807 | } | ||
2808 | ret = 0; | ||
2809 | } else { | ||
2810 | /*5211/5212*/ | ||
2811 | ret = ath5k_hw_register_timeout(ah, | ||
2812 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
2813 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
2814 | |||
2815 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
2816 | return -EIO; | ||
2817 | } | ||
2818 | |||
2819 | return ret; | ||
2820 | } | ||
2821 | #endif | ||
2822 | |||
2823 | /* | ||
2824 | * Update mib counters (statistics) | ||
2825 | */ | ||
2826 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | ||
2827 | struct ath5k_mib_stats *statistics) | ||
2828 | { | ||
2829 | ATH5K_TRACE(ah->ah_sc); | ||
2830 | /* Read-And-Clear */ | ||
2831 | statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | ||
2832 | statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | ||
2833 | statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | ||
2834 | statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | ||
2835 | statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
2836 | |||
2837 | /* Reset profile count registers on 5212*/ | ||
2838 | if (ah->ah_version == AR5K_AR5212) { | ||
2839 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
2840 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
2841 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
2842 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
2843 | } | ||
2844 | } | ||
2845 | |||
2846 | /** ath5k_hw_set_ack_bitrate - set bitrate for ACKs | ||
2847 | * | ||
2848 | * @ah: the &struct ath5k_hw | ||
2849 | * @high: determines if to use low bit rate or now | ||
2850 | */ | ||
2851 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | ||
2852 | { | ||
2853 | if (ah->ah_version != AR5K_AR5212) | ||
2854 | return; | ||
2855 | else { | ||
2856 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | ||
2857 | if (high) | ||
2858 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
2859 | else | ||
2860 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | ||
2861 | } | ||
2862 | } | ||
2863 | |||
2864 | |||
2865 | /* | ||
2866 | * ACK/CTS Timeouts | ||
2867 | */ | ||
2868 | |||
2869 | /* | ||
2870 | * Set ACK timeout on PCU | ||
2871 | */ | ||
2872 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
2873 | { | ||
2874 | ATH5K_TRACE(ah->ah_sc); | ||
2875 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | ||
2876 | ah->ah_turbo) <= timeout) | ||
2877 | return -EINVAL; | ||
2878 | |||
2879 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | ||
2880 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
2881 | |||
2882 | return 0; | ||
2883 | } | ||
2884 | |||
2885 | /* | ||
2886 | * Read the ACK timeout from PCU | ||
2887 | */ | ||
2888 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
2889 | { | ||
2890 | ATH5K_TRACE(ah->ah_sc); | ||
2891 | |||
2892 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
2893 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | ||
2894 | } | ||
2895 | |||
2896 | /* | ||
2897 | * Set CTS timeout on PCU | ||
2898 | */ | ||
2899 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | ||
2900 | { | ||
2901 | ATH5K_TRACE(ah->ah_sc); | ||
2902 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | ||
2903 | ah->ah_turbo) <= timeout) | ||
2904 | return -EINVAL; | ||
2905 | |||
2906 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | ||
2907 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | ||
2908 | |||
2909 | return 0; | ||
2910 | } | ||
2911 | |||
2912 | /* | ||
2913 | * Read CTS timeout from PCU | ||
2914 | */ | ||
2915 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
2916 | { | ||
2917 | ATH5K_TRACE(ah->ah_sc); | ||
2918 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
2919 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | ||
2920 | } | ||
2921 | |||
2922 | /* | ||
2923 | * Key table (WEP) functions | ||
2924 | */ | ||
2925 | |||
2926 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | ||
2927 | { | ||
2928 | unsigned int i; | ||
2929 | |||
2930 | ATH5K_TRACE(ah->ah_sc); | ||
2931 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
2932 | |||
2933 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | ||
2934 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | ||
2935 | |||
2936 | /* Set NULL encryption on non-5210*/ | ||
2937 | if (ah->ah_version != AR5K_AR5210) | ||
2938 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
2939 | AR5K_KEYTABLE_TYPE(entry)); | ||
2940 | |||
2941 | return 0; | ||
2942 | } | ||
2943 | |||
2944 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
2945 | { | ||
2946 | ATH5K_TRACE(ah->ah_sc); | ||
2947 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
2948 | |||
2949 | /* Check the validation flag at the end of the entry */ | ||
2950 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
2951 | AR5K_KEYTABLE_VALID; | ||
2952 | } | ||
2953 | |||
2954 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
2955 | const struct ieee80211_key_conf *key, const u8 *mac) | ||
2956 | { | ||
2957 | unsigned int i; | ||
2958 | __le32 key_v[5] = {}; | ||
2959 | u32 keytype; | ||
2960 | |||
2961 | ATH5K_TRACE(ah->ah_sc); | ||
2962 | |||
2963 | /* key->keylen comes in from mac80211 in bytes */ | ||
2964 | |||
2965 | if (key->keylen > AR5K_KEYTABLE_SIZE / 8) | ||
2966 | return -EOPNOTSUPP; | ||
2967 | |||
2968 | switch (key->keylen) { | ||
2969 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */ | ||
2970 | case 40 / 8: | ||
2971 | memcpy(&key_v[0], key->key, 5); | ||
2972 | keytype = AR5K_KEYTABLE_TYPE_40; | ||
2973 | break; | ||
2974 | |||
2975 | /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */ | ||
2976 | case 104 / 8: | ||
2977 | memcpy(&key_v[0], &key->key[0], 6); | ||
2978 | memcpy(&key_v[2], &key->key[6], 6); | ||
2979 | memcpy(&key_v[4], &key->key[12], 1); | ||
2980 | keytype = AR5K_KEYTABLE_TYPE_104; | ||
2981 | break; | ||
2982 | /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */ | ||
2983 | case 128 / 8: | ||
2984 | memcpy(&key_v[0], &key->key[0], 6); | ||
2985 | memcpy(&key_v[2], &key->key[6], 6); | ||
2986 | memcpy(&key_v[4], &key->key[12], 4); | ||
2987 | keytype = AR5K_KEYTABLE_TYPE_128; | ||
2988 | break; | ||
2989 | |||
2990 | default: | ||
2991 | return -EINVAL; /* shouldn't happen */ | ||
2992 | } | ||
2993 | |||
2994 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
2995 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
2996 | AR5K_KEYTABLE_OFF(entry, i)); | ||
2997 | |||
2998 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | ||
2999 | |||
3000 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | ||
3001 | } | ||
3002 | |||
3003 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | ||
3004 | { | ||
3005 | u32 low_id, high_id; | ||
3006 | |||
3007 | ATH5K_TRACE(ah->ah_sc); | ||
3008 | /* Invalid entry (key table overflow) */ | ||
3009 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
3010 | |||
3011 | /* MAC may be NULL if it's a broadcast key. In this case no need to | ||
3012 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | ||
3013 | if (unlikely(mac == NULL)) { | ||
3014 | low_id = 0xffffffff; | ||
3015 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | ||
3016 | } else { | ||
3017 | low_id = AR5K_LOW_ID(mac); | ||
3018 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | ||
3019 | } | ||
3020 | |||
3021 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | ||
3022 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | ||
3023 | |||
3024 | return 0; | ||
3025 | } | ||
3026 | |||
3027 | |||
3028 | /********************************************\ | ||
3029 | Queue Control Unit, DFS Control Unit Functions | ||
3030 | \********************************************/ | ||
3031 | |||
3032 | /* | ||
3033 | * Initialize a transmit queue | ||
3034 | */ | ||
3035 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | ||
3036 | struct ath5k_txq_info *queue_info) | ||
3037 | { | ||
3038 | unsigned int queue; | ||
3039 | int ret; | ||
3040 | |||
3041 | ATH5K_TRACE(ah->ah_sc); | ||
3042 | |||
3043 | /* | ||
3044 | * Get queue by type | ||
3045 | */ | ||
3046 | /*5210 only has 2 queues*/ | ||
3047 | if (ah->ah_version == AR5K_AR5210) { | ||
3048 | switch (queue_type) { | ||
3049 | case AR5K_TX_QUEUE_DATA: | ||
3050 | queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; | ||
3051 | break; | ||
3052 | case AR5K_TX_QUEUE_BEACON: | ||
3053 | case AR5K_TX_QUEUE_CAB: | ||
3054 | queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; | ||
3055 | break; | ||
3056 | default: | ||
3057 | return -EINVAL; | ||
3058 | } | ||
3059 | } else { | ||
3060 | switch (queue_type) { | ||
3061 | case AR5K_TX_QUEUE_DATA: | ||
3062 | for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; | ||
3063 | ah->ah_txq[queue].tqi_type != | ||
3064 | AR5K_TX_QUEUE_INACTIVE; queue++) { | ||
3065 | |||
3066 | if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) | ||
3067 | return -EINVAL; | ||
3068 | } | ||
3069 | break; | ||
3070 | case AR5K_TX_QUEUE_UAPSD: | ||
3071 | queue = AR5K_TX_QUEUE_ID_UAPSD; | ||
3072 | break; | ||
3073 | case AR5K_TX_QUEUE_BEACON: | ||
3074 | queue = AR5K_TX_QUEUE_ID_BEACON; | ||
3075 | break; | ||
3076 | case AR5K_TX_QUEUE_CAB: | ||
3077 | queue = AR5K_TX_QUEUE_ID_CAB; | ||
3078 | break; | ||
3079 | case AR5K_TX_QUEUE_XR_DATA: | ||
3080 | if (ah->ah_version != AR5K_AR5212) | ||
3081 | ATH5K_ERR(ah->ah_sc, | ||
3082 | "XR data queues only supported in" | ||
3083 | " 5212!\n"); | ||
3084 | queue = AR5K_TX_QUEUE_ID_XR_DATA; | ||
3085 | break; | ||
3086 | default: | ||
3087 | return -EINVAL; | ||
3088 | } | ||
3089 | } | ||
3090 | |||
3091 | /* | ||
3092 | * Setup internal queue structure | ||
3093 | */ | ||
3094 | memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); | ||
3095 | ah->ah_txq[queue].tqi_type = queue_type; | ||
3096 | |||
3097 | if (queue_info != NULL) { | ||
3098 | queue_info->tqi_type = queue_type; | ||
3099 | ret = ath5k_hw_setup_tx_queueprops(ah, queue, queue_info); | ||
3100 | if (ret) | ||
3101 | return ret; | ||
3102 | } | ||
3103 | /* | ||
3104 | * We use ah_txq_status to hold a temp value for | ||
3105 | * the Secondary interrupt mask registers on 5211+ | ||
3106 | * check out ath5k_hw_reset_tx_queue | ||
3107 | */ | ||
3108 | AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); | ||
3109 | |||
3110 | return queue; | ||
3111 | } | ||
3112 | |||
3113 | /* | ||
3114 | * Setup a transmit queue | ||
3115 | */ | ||
3116 | int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
3117 | const struct ath5k_txq_info *queue_info) | ||
3118 | { | ||
3119 | ATH5K_TRACE(ah->ah_sc); | ||
3120 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3121 | |||
3122 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3123 | return -EIO; | ||
3124 | |||
3125 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | ||
3126 | |||
3127 | /*XXX: Is this supported on 5210 ?*/ | ||
3128 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | ||
3129 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | ||
3130 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | ||
3131 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | ||
3132 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
3133 | |||
3134 | return 0; | ||
3135 | } | ||
3136 | |||
3137 | /* | ||
3138 | * Get properties for a specific transmit queue | ||
3139 | */ | ||
3140 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
3141 | struct ath5k_txq_info *queue_info) | ||
3142 | { | ||
3143 | ATH5K_TRACE(ah->ah_sc); | ||
3144 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | ||
3145 | return 0; | ||
3146 | } | ||
3147 | |||
3148 | /* | ||
3149 | * Set a transmit queue inactive | ||
3150 | */ | ||
3151 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
3152 | { | ||
3153 | ATH5K_TRACE(ah->ah_sc); | ||
3154 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
3155 | return; | ||
3156 | |||
3157 | /* This queue will be skipped in further operations */ | ||
3158 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | ||
3159 | /*For SIMR setup*/ | ||
3160 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
3161 | } | ||
3162 | |||
3163 | /* | ||
3164 | * Set DFS params for a transmit queue | ||
3165 | */ | ||
3166 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
3167 | { | ||
3168 | u32 cw_min, cw_max, retry_lg, retry_sh; | ||
3169 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | ||
3170 | |||
3171 | ATH5K_TRACE(ah->ah_sc); | ||
3172 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3173 | |||
3174 | tq = &ah->ah_txq[queue]; | ||
3175 | |||
3176 | if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3177 | return 0; | ||
3178 | |||
3179 | if (ah->ah_version == AR5K_AR5210) { | ||
3180 | /* Only handle data queues, others will be ignored */ | ||
3181 | if (tq->tqi_type != AR5K_TX_QUEUE_DATA) | ||
3182 | return 0; | ||
3183 | |||
3184 | /* Set Slot time */ | ||
3185 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3186 | AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, | ||
3187 | AR5K_SLOT_TIME); | ||
3188 | /* Set ACK_CTS timeout */ | ||
3189 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3190 | AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : | ||
3191 | AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); | ||
3192 | /* Set Transmit Latency */ | ||
3193 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3194 | AR5K_INIT_TRANSMIT_LATENCY_TURBO : | ||
3195 | AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); | ||
3196 | /* Set IFS0 */ | ||
3197 | if (ah->ah_turbo == true) | ||
3198 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | ||
3199 | (ah->ah_aifs + tq->tqi_aifs) * | ||
3200 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
3201 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | ||
3202 | AR5K_IFS0); | ||
3203 | else | ||
3204 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | ||
3205 | (ah->ah_aifs + tq->tqi_aifs) * | ||
3206 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | ||
3207 | AR5K_INIT_SIFS, AR5K_IFS0); | ||
3208 | |||
3209 | /* Set IFS1 */ | ||
3210 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3211 | AR5K_INIT_PROTO_TIME_CNTRL_TURBO : | ||
3212 | AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); | ||
3213 | /* Set PHY register 0x9844 (??) */ | ||
3214 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3215 | (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 : | ||
3216 | (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C, | ||
3217 | AR5K_PHY(17)); | ||
3218 | /* Set Frame Control Register */ | ||
3219 | ath5k_hw_reg_write(ah, ah->ah_turbo == true ? | ||
3220 | (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | | ||
3221 | AR5K_PHY_TURBO_SHORT | 0x2020) : | ||
3222 | (AR5K_PHY_FRAME_CTL_INI | 0x1020), | ||
3223 | AR5K_PHY_FRAME_CTL_5210); | ||
3224 | } | ||
3225 | |||
3226 | /* | ||
3227 | * Calculate cwmin/max by channel mode | ||
3228 | */ | ||
3229 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
3230 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | ||
3231 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
3232 | /*XR is only supported on 5212*/ | ||
3233 | if (IS_CHAN_XR(ah->ah_current_channel) && | ||
3234 | ah->ah_version == AR5K_AR5212) { | ||
3235 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
3236 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
3237 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
3238 | /*B mode is not supported on 5210*/ | ||
3239 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
3240 | ah->ah_version != AR5K_AR5210) { | ||
3241 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
3242 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
3243 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
3244 | } | ||
3245 | |||
3246 | cw_min = 1; | ||
3247 | while (cw_min < ah->ah_cw_min) | ||
3248 | cw_min = (cw_min << 1) | 1; | ||
3249 | |||
3250 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
3251 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
3252 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
3253 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
3254 | |||
3255 | /* | ||
3256 | * Calculate and set retry limits | ||
3257 | */ | ||
3258 | if (ah->ah_software_retry == true) { | ||
3259 | /* XXX Need to test this */ | ||
3260 | retry_lg = ah->ah_limit_tx_retries; | ||
3261 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? | ||
3262 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; | ||
3263 | } else { | ||
3264 | retry_lg = AR5K_INIT_LG_RETRY; | ||
3265 | retry_sh = AR5K_INIT_SH_RETRY; | ||
3266 | } | ||
3267 | |||
3268 | /*No QCU/DCU [5210]*/ | ||
3269 | if (ah->ah_version == AR5K_AR5210) { | ||
3270 | ath5k_hw_reg_write(ah, | ||
3271 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | ||
3272 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
3273 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | ||
3274 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
3275 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | ||
3276 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | ||
3277 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
3278 | AR5K_NODCU_RETRY_LMT); | ||
3279 | } else { | ||
3280 | /*QCU/DCU [5211+]*/ | ||
3281 | ath5k_hw_reg_write(ah, | ||
3282 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
3283 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | | ||
3284 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
3285 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | | ||
3286 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | | ||
3287 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), | ||
3288 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | ||
3289 | |||
3290 | /*===Rest is also for QCU/DCU only [5211+]===*/ | ||
3291 | |||
3292 | /* | ||
3293 | * Set initial content window (cw_min/cw_max) | ||
3294 | * and arbitrated interframe space (aifs)... | ||
3295 | */ | ||
3296 | ath5k_hw_reg_write(ah, | ||
3297 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | ||
3298 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | ||
3299 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | ||
3300 | AR5K_DCU_LCL_IFS_AIFS), | ||
3301 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | ||
3302 | |||
3303 | /* | ||
3304 | * Set misc registers | ||
3305 | */ | ||
3306 | ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, | ||
3307 | AR5K_QUEUE_MISC(queue)); | ||
3308 | |||
3309 | if (tq->tqi_cbr_period) { | ||
3310 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | ||
3311 | AR5K_QCU_CBRCFG_INTVAL) | | ||
3312 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, | ||
3313 | AR5K_QCU_CBRCFG_ORN_THRES), | ||
3314 | AR5K_QUEUE_CBRCFG(queue)); | ||
3315 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3316 | AR5K_QCU_MISC_FRSHED_CBR); | ||
3317 | if (tq->tqi_cbr_overflow_limit) | ||
3318 | AR5K_REG_ENABLE_BITS(ah, | ||
3319 | AR5K_QUEUE_MISC(queue), | ||
3320 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | ||
3321 | } | ||
3322 | |||
3323 | if (tq->tqi_ready_time) | ||
3324 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | ||
3325 | AR5K_QCU_RDYTIMECFG_INTVAL) | | ||
3326 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
3327 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
3328 | |||
3329 | if (tq->tqi_burst_time) { | ||
3330 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, | ||
3331 | AR5K_DCU_CHAN_TIME_DUR) | | ||
3332 | AR5K_DCU_CHAN_TIME_ENABLE, | ||
3333 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); | ||
3334 | |||
3335 | if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) | ||
3336 | AR5K_REG_ENABLE_BITS(ah, | ||
3337 | AR5K_QUEUE_MISC(queue), | ||
3338 | AR5K_QCU_MISC_TXE); | ||
3339 | } | ||
3340 | |||
3341 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) | ||
3342 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, | ||
3343 | AR5K_QUEUE_DFS_MISC(queue)); | ||
3344 | |||
3345 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) | ||
3346 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, | ||
3347 | AR5K_QUEUE_DFS_MISC(queue)); | ||
3348 | |||
3349 | /* | ||
3350 | * Set registers by queue type | ||
3351 | */ | ||
3352 | switch (tq->tqi_type) { | ||
3353 | case AR5K_TX_QUEUE_BEACON: | ||
3354 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3355 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
3356 | AR5K_QCU_MISC_CBREXP_BCN | | ||
3357 | AR5K_QCU_MISC_BCN_ENABLE); | ||
3358 | |||
3359 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
3360 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
3361 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | ||
3362 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | ||
3363 | AR5K_DCU_MISC_BCN_ENABLE); | ||
3364 | |||
3365 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
3366 | (AR5K_TUNE_SW_BEACON_RESP - | ||
3367 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
3368 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
3369 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
3370 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
3371 | break; | ||
3372 | |||
3373 | case AR5K_TX_QUEUE_CAB: | ||
3374 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3375 | AR5K_QCU_MISC_FRSHED_DBA_GT | | ||
3376 | AR5K_QCU_MISC_CBREXP | | ||
3377 | AR5K_QCU_MISC_CBREXP_BCN); | ||
3378 | |||
3379 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
3380 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | ||
3381 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | ||
3382 | break; | ||
3383 | |||
3384 | case AR5K_TX_QUEUE_UAPSD: | ||
3385 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
3386 | AR5K_QCU_MISC_CBREXP); | ||
3387 | break; | ||
3388 | |||
3389 | case AR5K_TX_QUEUE_DATA: | ||
3390 | default: | ||
3391 | break; | ||
3392 | } | ||
3393 | |||
3394 | /* | ||
3395 | * Enable interrupts for this tx queue | ||
3396 | * in the secondary interrupt mask registers | ||
3397 | */ | ||
3398 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) | ||
3399 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); | ||
3400 | |||
3401 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) | ||
3402 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); | ||
3403 | |||
3404 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) | ||
3405 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); | ||
3406 | |||
3407 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) | ||
3408 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); | ||
3409 | |||
3410 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) | ||
3411 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); | ||
3412 | |||
3413 | |||
3414 | /* Update secondary interrupt mask registers */ | ||
3415 | ah->ah_txq_imr_txok &= ah->ah_txq_status; | ||
3416 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; | ||
3417 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; | ||
3418 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; | ||
3419 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; | ||
3420 | |||
3421 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, | ||
3422 | AR5K_SIMR0_QCU_TXOK) | | ||
3423 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, | ||
3424 | AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); | ||
3425 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, | ||
3426 | AR5K_SIMR1_QCU_TXERR) | | ||
3427 | AR5K_REG_SM(ah->ah_txq_imr_txeol, | ||
3428 | AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); | ||
3429 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn, | ||
3430 | AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2); | ||
3431 | } | ||
3432 | |||
3433 | return 0; | ||
3434 | } | ||
3435 | |||
3436 | /* | ||
3437 | * Get number of pending frames | ||
3438 | * for a specific queue [5211+] | ||
3439 | */ | ||
3440 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { | ||
3441 | ATH5K_TRACE(ah->ah_sc); | ||
3442 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
3443 | |||
3444 | /* Return if queue is declared inactive */ | ||
3445 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
3446 | return false; | ||
3447 | |||
3448 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
3449 | if (ah->ah_version == AR5K_AR5210) | ||
3450 | return false; | ||
3451 | |||
3452 | return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; | ||
3453 | } | ||
3454 | |||
3455 | /* | ||
3456 | * Set slot time | ||
3457 | */ | ||
3458 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | ||
3459 | { | ||
3460 | ATH5K_TRACE(ah->ah_sc); | ||
3461 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | ||
3462 | return -EINVAL; | ||
3463 | |||
3464 | if (ah->ah_version == AR5K_AR5210) | ||
3465 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | ||
3466 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
3467 | else | ||
3468 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | ||
3469 | |||
3470 | return 0; | ||
3471 | } | ||
3472 | |||
3473 | /* | ||
3474 | * Get slot time | ||
3475 | */ | ||
3476 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | ||
3477 | { | ||
3478 | ATH5K_TRACE(ah->ah_sc); | ||
3479 | if (ah->ah_version == AR5K_AR5210) | ||
3480 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | ||
3481 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
3482 | else | ||
3483 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | ||
3484 | } | ||
3485 | |||
3486 | |||
3487 | /******************************\ | ||
3488 | Hardware Descriptor Functions | ||
3489 | \******************************/ | ||
3490 | |||
3491 | /* | ||
3492 | * TX Descriptor | ||
3493 | */ | ||
3494 | |||
3495 | /* | ||
3496 | * Initialize the 2-word tx descriptor on 5210/5211 | ||
3497 | */ | ||
3498 | static int | ||
3499 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
3500 | unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, | ||
3501 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | ||
3502 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | ||
3503 | unsigned int rtscts_rate, unsigned int rtscts_duration) | ||
3504 | { | ||
3505 | u32 frame_type; | ||
3506 | struct ath5k_hw_2w_tx_desc *tx_desc; | ||
3507 | unsigned int buff_len; | ||
3508 | |||
3509 | tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; | ||
3510 | |||
3511 | /* | ||
3512 | * Validate input | ||
3513 | * - Zero retries don't make sense. | ||
3514 | * - A zero rate will put the HW into a mode where it continously sends | ||
3515 | * noise on the channel, so it is important to avoid this. | ||
3516 | */ | ||
3517 | if (unlikely(tx_tries0 == 0)) { | ||
3518 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
3519 | WARN_ON(1); | ||
3520 | return -EINVAL; | ||
3521 | } | ||
3522 | if (unlikely(tx_rate0 == 0)) { | ||
3523 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3524 | WARN_ON(1); | ||
3525 | return -EINVAL; | ||
3526 | } | ||
3527 | |||
3528 | /* Clear status descriptor */ | ||
3529 | memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status)); | ||
3530 | |||
3531 | /* Initialize control descriptor */ | ||
3532 | tx_desc->tx_control_0 = 0; | ||
3533 | tx_desc->tx_control_1 = 0; | ||
3534 | |||
3535 | /* Setup control descriptor */ | ||
3536 | |||
3537 | /* Verify and set frame length */ | ||
3538 | if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | ||
3539 | return -EINVAL; | ||
3540 | |||
3541 | tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; | ||
3542 | |||
3543 | /* Verify and set buffer length */ | ||
3544 | buff_len = pkt_len - FCS_LEN; | ||
3545 | |||
3546 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
3547 | if(type == AR5K_PKT_TYPE_BEACON) | ||
3548 | buff_len = roundup(buff_len, 4); | ||
3549 | |||
3550 | if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) | ||
3551 | return -EINVAL; | ||
3552 | |||
3553 | tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | ||
3554 | |||
3555 | /* | ||
3556 | * Verify and set header length | ||
3557 | * XXX: I only found that on 5210 code, does it work on 5211 ? | ||
3558 | */ | ||
3559 | if (ah->ah_version == AR5K_AR5210) { | ||
3560 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | ||
3561 | return -EINVAL; | ||
3562 | tx_desc->tx_control_0 |= | ||
3563 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | ||
3564 | } | ||
3565 | |||
3566 | /*Diferences between 5210-5211*/ | ||
3567 | if (ah->ah_version == AR5K_AR5210) { | ||
3568 | switch (type) { | ||
3569 | case AR5K_PKT_TYPE_BEACON: | ||
3570 | case AR5K_PKT_TYPE_PROBE_RESP: | ||
3571 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; | ||
3572 | case AR5K_PKT_TYPE_PIFS: | ||
3573 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | ||
3574 | default: | ||
3575 | frame_type = type /*<< 2 ?*/; | ||
3576 | } | ||
3577 | |||
3578 | tx_desc->tx_control_0 |= | ||
3579 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | ||
3580 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
3581 | } else { | ||
3582 | tx_desc->tx_control_0 |= | ||
3583 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | | ||
3584 | AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
3585 | tx_desc->tx_control_1 |= | ||
3586 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | ||
3587 | } | ||
3588 | #define _TX_FLAGS(_c, _flag) \ | ||
3589 | if (flags & AR5K_TXDESC_##_flag) \ | ||
3590 | tx_desc->tx_control_##_c |= \ | ||
3591 | AR5K_2W_TX_DESC_CTL##_c##_##_flag | ||
3592 | |||
3593 | _TX_FLAGS(0, CLRDMASK); | ||
3594 | _TX_FLAGS(0, VEOL); | ||
3595 | _TX_FLAGS(0, INTREQ); | ||
3596 | _TX_FLAGS(0, RTSENA); | ||
3597 | _TX_FLAGS(1, NOACK); | ||
3598 | |||
3599 | #undef _TX_FLAGS | ||
3600 | |||
3601 | /* | ||
3602 | * WEP crap | ||
3603 | */ | ||
3604 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
3605 | tx_desc->tx_control_0 |= | ||
3606 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
3607 | tx_desc->tx_control_1 |= | ||
3608 | AR5K_REG_SM(key_index, | ||
3609 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
3610 | } | ||
3611 | |||
3612 | /* | ||
3613 | * RTS/CTS Duration [5210 ?] | ||
3614 | */ | ||
3615 | if ((ah->ah_version == AR5K_AR5210) && | ||
3616 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | ||
3617 | tx_desc->tx_control_1 |= rtscts_duration & | ||
3618 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | ||
3619 | |||
3620 | return 0; | ||
3621 | } | ||
3622 | |||
3623 | /* | ||
3624 | * Initialize the 4-word tx descriptor on 5212 | ||
3625 | */ | ||
3626 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | ||
3627 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | ||
3628 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | ||
3629 | unsigned int tx_tries0, unsigned int key_index, | ||
3630 | unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, | ||
3631 | unsigned int rtscts_duration) | ||
3632 | { | ||
3633 | struct ath5k_hw_4w_tx_desc *tx_desc; | ||
3634 | struct ath5k_hw_tx_status *tx_status; | ||
3635 | unsigned int buff_len; | ||
3636 | |||
3637 | ATH5K_TRACE(ah->ah_sc); | ||
3638 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | ||
3639 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; | ||
3640 | |||
3641 | /* | ||
3642 | * Validate input | ||
3643 | * - Zero retries don't make sense. | ||
3644 | * - A zero rate will put the HW into a mode where it continously sends | ||
3645 | * noise on the channel, so it is important to avoid this. | ||
3646 | */ | ||
3647 | if (unlikely(tx_tries0 == 0)) { | ||
3648 | ATH5K_ERR(ah->ah_sc, "zero retries\n"); | ||
3649 | WARN_ON(1); | ||
3650 | return -EINVAL; | ||
3651 | } | ||
3652 | if (unlikely(tx_rate0 == 0)) { | ||
3653 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3654 | WARN_ON(1); | ||
3655 | return -EINVAL; | ||
3656 | } | ||
3657 | |||
3658 | /* Clear status descriptor */ | ||
3659 | memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status)); | ||
3660 | |||
3661 | /* Initialize control descriptor */ | ||
3662 | tx_desc->tx_control_0 = 0; | ||
3663 | tx_desc->tx_control_1 = 0; | ||
3664 | tx_desc->tx_control_2 = 0; | ||
3665 | tx_desc->tx_control_3 = 0; | ||
3666 | |||
3667 | /* Setup control descriptor */ | ||
3668 | |||
3669 | /* Verify and set frame length */ | ||
3670 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | ||
3671 | return -EINVAL; | ||
3672 | |||
3673 | tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | ||
3674 | |||
3675 | /* Verify and set buffer length */ | ||
3676 | buff_len = pkt_len - FCS_LEN; | ||
3677 | |||
3678 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
3679 | if(type == AR5K_PKT_TYPE_BEACON) | ||
3680 | buff_len = roundup(buff_len, 4); | ||
3681 | |||
3682 | if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | ||
3683 | return -EINVAL; | ||
3684 | |||
3685 | tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | ||
3686 | |||
3687 | tx_desc->tx_control_0 |= | ||
3688 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | ||
3689 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | ||
3690 | tx_desc->tx_control_1 |= AR5K_REG_SM(type, | ||
3691 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | ||
3692 | tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | ||
3693 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | ||
3694 | tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
3695 | |||
3696 | #define _TX_FLAGS(_c, _flag) \ | ||
3697 | if (flags & AR5K_TXDESC_##_flag) \ | ||
3698 | tx_desc->tx_control_##_c |= \ | ||
3699 | AR5K_4W_TX_DESC_CTL##_c##_##_flag | ||
3700 | |||
3701 | _TX_FLAGS(0, CLRDMASK); | ||
3702 | _TX_FLAGS(0, VEOL); | ||
3703 | _TX_FLAGS(0, INTREQ); | ||
3704 | _TX_FLAGS(0, RTSENA); | ||
3705 | _TX_FLAGS(0, CTSENA); | ||
3706 | _TX_FLAGS(1, NOACK); | ||
3707 | |||
3708 | #undef _TX_FLAGS | ||
3709 | |||
3710 | /* | ||
3711 | * WEP crap | ||
3712 | */ | ||
3713 | if (key_index != AR5K_TXKEYIX_INVALID) { | ||
3714 | tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | ||
3715 | tx_desc->tx_control_1 |= AR5K_REG_SM(key_index, | ||
3716 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | ||
3717 | } | ||
3718 | |||
3719 | /* | ||
3720 | * RTS/CTS | ||
3721 | */ | ||
3722 | if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { | ||
3723 | if ((flags & AR5K_TXDESC_RTSENA) && | ||
3724 | (flags & AR5K_TXDESC_CTSENA)) | ||
3725 | return -EINVAL; | ||
3726 | tx_desc->tx_control_2 |= rtscts_duration & | ||
3727 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | ||
3728 | tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | ||
3729 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | ||
3730 | } | ||
3731 | |||
3732 | return 0; | ||
3733 | } | ||
3734 | |||
3735 | /* | ||
3736 | * Initialize a 4-word multirate tx descriptor on 5212 | ||
3737 | */ | ||
3738 | static bool | ||
3739 | ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
3740 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, | ||
3741 | unsigned int tx_rate3, u_int tx_tries3) | ||
3742 | { | ||
3743 | struct ath5k_hw_4w_tx_desc *tx_desc; | ||
3744 | |||
3745 | /* | ||
3746 | * Rates can be 0 as long as the retry count is 0 too. | ||
3747 | * A zero rate and nonzero retry count will put the HW into a mode where | ||
3748 | * it continously sends noise on the channel, so it is important to | ||
3749 | * avoid this. | ||
3750 | */ | ||
3751 | if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || | ||
3752 | (tx_rate2 == 0 && tx_tries2 != 0) || | ||
3753 | (tx_rate3 == 0 && tx_tries3 != 0))) { | ||
3754 | ATH5K_ERR(ah->ah_sc, "zero rate\n"); | ||
3755 | WARN_ON(1); | ||
3756 | return -EINVAL; | ||
3757 | } | ||
3758 | |||
3759 | if (ah->ah_version == AR5K_AR5212) { | ||
3760 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | ||
3761 | |||
3762 | #define _XTX_TRIES(_n) \ | ||
3763 | if (tx_tries##_n) { \ | ||
3764 | tx_desc->tx_control_2 |= \ | ||
3765 | AR5K_REG_SM(tx_tries##_n, \ | ||
3766 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ | ||
3767 | tx_desc->tx_control_3 |= \ | ||
3768 | AR5K_REG_SM(tx_rate##_n, \ | ||
3769 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ | ||
3770 | } | ||
3771 | |||
3772 | _XTX_TRIES(1); | ||
3773 | _XTX_TRIES(2); | ||
3774 | _XTX_TRIES(3); | ||
3775 | |||
3776 | #undef _XTX_TRIES | ||
3777 | |||
3778 | return true; | ||
3779 | } | ||
3780 | |||
3781 | return false; | ||
3782 | } | ||
3783 | |||
3784 | /* | ||
3785 | * Proccess the tx status descriptor on 5210/5211 | ||
3786 | */ | ||
3787 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | ||
3788 | struct ath5k_desc *desc) | ||
3789 | { | ||
3790 | struct ath5k_hw_tx_status *tx_status; | ||
3791 | struct ath5k_hw_2w_tx_desc *tx_desc; | ||
3792 | |||
3793 | tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; | ||
3794 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0]; | ||
3795 | |||
3796 | /* No frame has been send or error */ | ||
3797 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | ||
3798 | return -EINPROGRESS; | ||
3799 | |||
3800 | /* | ||
3801 | * Get descriptor status | ||
3802 | */ | ||
3803 | desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
3804 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
3805 | desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3806 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
3807 | desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3808 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
3809 | /*TODO: desc->ds_us.tx.ts_virtcol + test*/ | ||
3810 | desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
3811 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
3812 | desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
3813 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
3814 | desc->ds_us.tx.ts_antenna = 1; | ||
3815 | desc->ds_us.tx.ts_status = 0; | ||
3816 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0, | ||
3817 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
3818 | |||
3819 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | ||
3820 | if (tx_status->tx_status_0 & | ||
3821 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
3822 | desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; | ||
3823 | |||
3824 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
3825 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; | ||
3826 | |||
3827 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
3828 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; | ||
3829 | } | ||
3830 | |||
3831 | return 0; | ||
3832 | } | ||
3833 | |||
3834 | /* | ||
3835 | * Proccess a tx descriptor on 5212 | ||
3836 | */ | ||
3837 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | ||
3838 | struct ath5k_desc *desc) | ||
3839 | { | ||
3840 | struct ath5k_hw_tx_status *tx_status; | ||
3841 | struct ath5k_hw_4w_tx_desc *tx_desc; | ||
3842 | |||
3843 | ATH5K_TRACE(ah->ah_sc); | ||
3844 | tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; | ||
3845 | tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; | ||
3846 | |||
3847 | /* No frame has been send or error */ | ||
3848 | if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) | ||
3849 | return -EINPROGRESS; | ||
3850 | |||
3851 | /* | ||
3852 | * Get descriptor status | ||
3853 | */ | ||
3854 | desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | ||
3855 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | ||
3856 | desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3857 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | ||
3858 | desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | ||
3859 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | ||
3860 | desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | ||
3861 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | ||
3862 | desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | ||
3863 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | ||
3864 | desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 & | ||
3865 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | ||
3866 | desc->ds_us.tx.ts_status = 0; | ||
3867 | |||
3868 | switch (AR5K_REG_MS(tx_status->tx_status_1, | ||
3869 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { | ||
3870 | case 0: | ||
3871 | desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 & | ||
3872 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
3873 | break; | ||
3874 | case 1: | ||
3875 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | ||
3876 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | ||
3877 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | ||
3878 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
3879 | break; | ||
3880 | case 2: | ||
3881 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | ||
3882 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
3883 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | ||
3884 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
3885 | break; | ||
3886 | case 3: | ||
3887 | desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, | ||
3888 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
3889 | desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, | ||
3890 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); | ||
3891 | break; | ||
3892 | } | ||
3893 | |||
3894 | if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ | ||
3895 | if (tx_status->tx_status_0 & | ||
3896 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
3897 | desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; | ||
3898 | |||
3899 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | ||
3900 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; | ||
3901 | |||
3902 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | ||
3903 | desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; | ||
3904 | } | ||
3905 | |||
3906 | return 0; | ||
3907 | } | ||
3908 | |||
3909 | /* | ||
3910 | * RX Descriptor | ||
3911 | */ | ||
3912 | |||
3913 | /* | ||
3914 | * Initialize an rx descriptor | ||
3915 | */ | ||
3916 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
3917 | u32 size, unsigned int flags) | ||
3918 | { | ||
3919 | struct ath5k_rx_desc *rx_desc; | ||
3920 | |||
3921 | ATH5K_TRACE(ah->ah_sc); | ||
3922 | rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0; | ||
3923 | |||
3924 | /* | ||
3925 | *Clear ds_hw | ||
3926 | * If we don't clean the status descriptor, | ||
3927 | * while scanning we get too many results, | ||
3928 | * most of them virtual, after some secs | ||
3929 | * of scanning system hangs. M.F. | ||
3930 | */ | ||
3931 | memset(desc->ds_hw, 0, sizeof(desc->ds_hw)); | ||
3932 | |||
3933 | /*Initialize rx descriptor*/ | ||
3934 | rx_desc->rx_control_0 = 0; | ||
3935 | rx_desc->rx_control_1 = 0; | ||
3936 | |||
3937 | /* Setup descriptor */ | ||
3938 | rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | ||
3939 | if (unlikely(rx_desc->rx_control_1 != size)) | ||
3940 | return -EINVAL; | ||
3941 | |||
3942 | if (flags & AR5K_RXDESC_INTREQ) | ||
3943 | rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | ||
3944 | |||
3945 | return 0; | ||
3946 | } | ||
3947 | |||
3948 | /* | ||
3949 | * Proccess the rx status descriptor on 5210/5211 | ||
3950 | */ | ||
3951 | static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, | ||
3952 | struct ath5k_desc *desc) | ||
3953 | { | ||
3954 | struct ath5k_hw_old_rx_status *rx_status; | ||
3955 | |||
3956 | rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0]; | ||
3957 | |||
3958 | /* No frame received / not ready */ | ||
3959 | if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE) | ||
3960 | == 0)) | ||
3961 | return -EINPROGRESS; | ||
3962 | |||
3963 | /* | ||
3964 | * Frame receive status | ||
3965 | */ | ||
3966 | desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & | ||
3967 | AR5K_OLD_RX_DESC_STATUS0_DATA_LEN; | ||
3968 | desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
3969 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
3970 | desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
3971 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE); | ||
3972 | desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & | ||
3973 | AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
3974 | desc->ds_us.rx.rs_more = rx_status->rx_status_0 & | ||
3975 | AR5K_OLD_RX_DESC_STATUS0_MORE; | ||
3976 | desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
3977 | AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
3978 | desc->ds_us.rx.rs_status = 0; | ||
3979 | |||
3980 | /* | ||
3981 | * Key table status | ||
3982 | */ | ||
3983 | if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
3984 | desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
3985 | AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX); | ||
3986 | else | ||
3987 | desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; | ||
3988 | |||
3989 | /* | ||
3990 | * Receive/descriptor errors | ||
3991 | */ | ||
3992 | if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK) | ||
3993 | == 0) { | ||
3994 | if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR) | ||
3995 | desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; | ||
3996 | |||
3997 | if (rx_status->rx_status_1 & | ||
3998 | AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN) | ||
3999 | desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO; | ||
4000 | |||
4001 | if (rx_status->rx_status_1 & | ||
4002 | AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) { | ||
4003 | desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; | ||
4004 | desc->ds_us.rx.rs_phyerr = | ||
4005 | AR5K_REG_MS(rx_status->rx_status_1, | ||
4006 | AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR); | ||
4007 | } | ||
4008 | |||
4009 | if (rx_status->rx_status_1 & | ||
4010 | AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
4011 | desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; | ||
4012 | } | ||
4013 | |||
4014 | return 0; | ||
4015 | } | ||
4016 | |||
4017 | /* | ||
4018 | * Proccess the rx status descriptor on 5212 | ||
4019 | */ | ||
4020 | static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, | ||
4021 | struct ath5k_desc *desc) | ||
4022 | { | ||
4023 | struct ath5k_hw_new_rx_status *rx_status; | ||
4024 | struct ath5k_hw_rx_error *rx_err; | ||
4025 | |||
4026 | ATH5K_TRACE(ah->ah_sc); | ||
4027 | rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0]; | ||
4028 | |||
4029 | /* Overlay on error */ | ||
4030 | rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0]; | ||
4031 | |||
4032 | /* No frame received / not ready */ | ||
4033 | if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE) | ||
4034 | == 0)) | ||
4035 | return -EINPROGRESS; | ||
4036 | |||
4037 | /* | ||
4038 | * Frame receive status | ||
4039 | */ | ||
4040 | desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & | ||
4041 | AR5K_NEW_RX_DESC_STATUS0_DATA_LEN; | ||
4042 | desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
4043 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL); | ||
4044 | desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | ||
4045 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE); | ||
4046 | desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & | ||
4047 | AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA; | ||
4048 | desc->ds_us.rx.rs_more = rx_status->rx_status_0 & | ||
4049 | AR5K_NEW_RX_DESC_STATUS0_MORE; | ||
4050 | desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
4051 | AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | ||
4052 | desc->ds_us.rx.rs_status = 0; | ||
4053 | |||
4054 | /* | ||
4055 | * Key table status | ||
4056 | */ | ||
4057 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID) | ||
4058 | desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | ||
4059 | AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX); | ||
4060 | else | ||
4061 | desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; | ||
4062 | |||
4063 | /* | ||
4064 | * Receive/descriptor errors | ||
4065 | */ | ||
4066 | if ((rx_status->rx_status_1 & | ||
4067 | AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { | ||
4068 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR) | ||
4069 | desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; | ||
4070 | |||
4071 | if (rx_status->rx_status_1 & | ||
4072 | AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) { | ||
4073 | desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; | ||
4074 | desc->ds_us.rx.rs_phyerr = | ||
4075 | AR5K_REG_MS(rx_err->rx_error_1, | ||
4076 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | ||
4077 | } | ||
4078 | |||
4079 | if (rx_status->rx_status_1 & | ||
4080 | AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
4081 | desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; | ||
4082 | |||
4083 | if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR) | ||
4084 | desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC; | ||
4085 | } | ||
4086 | |||
4087 | return 0; | ||
4088 | } | ||
4089 | |||
4090 | |||
4091 | /****************\ | ||
4092 | GPIO Functions | ||
4093 | \****************/ | ||
4094 | |||
4095 | /* | ||
4096 | * Set led state | ||
4097 | */ | ||
4098 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | ||
4099 | { | ||
4100 | u32 led; | ||
4101 | /*5210 has different led mode handling*/ | ||
4102 | u32 led_5210; | ||
4103 | |||
4104 | ATH5K_TRACE(ah->ah_sc); | ||
4105 | |||
4106 | /*Reset led status*/ | ||
4107 | if (ah->ah_version != AR5K_AR5210) | ||
4108 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
4109 | AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); | ||
4110 | else | ||
4111 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); | ||
4112 | |||
4113 | /* | ||
4114 | * Some blinking values, define at your wish | ||
4115 | */ | ||
4116 | switch (state) { | ||
4117 | case AR5K_LED_SCAN: | ||
4118 | case AR5K_LED_AUTH: | ||
4119 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; | ||
4120 | led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; | ||
4121 | break; | ||
4122 | |||
4123 | case AR5K_LED_INIT: | ||
4124 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; | ||
4125 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
4126 | break; | ||
4127 | |||
4128 | case AR5K_LED_ASSOC: | ||
4129 | case AR5K_LED_RUN: | ||
4130 | led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; | ||
4131 | led_5210 = AR5K_PCICFG_LED_ASSOC; | ||
4132 | break; | ||
4133 | |||
4134 | default: | ||
4135 | led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; | ||
4136 | led_5210 = AR5K_PCICFG_LED_PEND; | ||
4137 | break; | ||
4138 | } | ||
4139 | |||
4140 | /*Write new status to the register*/ | ||
4141 | if (ah->ah_version != AR5K_AR5210) | ||
4142 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); | ||
4143 | else | ||
4144 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); | ||
4145 | } | ||
4146 | |||
4147 | /* | ||
4148 | * Set GPIO outputs | ||
4149 | */ | ||
4150 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | ||
4151 | { | ||
4152 | ATH5K_TRACE(ah->ah_sc); | ||
4153 | if (gpio > AR5K_NUM_GPIO) | ||
4154 | return -EINVAL; | ||
4155 | |||
4156 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~ | ||
4157 | AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); | ||
4158 | |||
4159 | return 0; | ||
4160 | } | ||
4161 | |||
4162 | /* | ||
4163 | * Set GPIO inputs | ||
4164 | */ | ||
4165 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | ||
4166 | { | ||
4167 | ATH5K_TRACE(ah->ah_sc); | ||
4168 | if (gpio > AR5K_NUM_GPIO) | ||
4169 | return -EINVAL; | ||
4170 | |||
4171 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~ | ||
4172 | AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); | ||
4173 | |||
4174 | return 0; | ||
4175 | } | ||
4176 | |||
4177 | /* | ||
4178 | * Get GPIO state | ||
4179 | */ | ||
4180 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | ||
4181 | { | ||
4182 | ATH5K_TRACE(ah->ah_sc); | ||
4183 | if (gpio > AR5K_NUM_GPIO) | ||
4184 | return 0xffffffff; | ||
4185 | |||
4186 | /* GPIO input magic */ | ||
4187 | return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & | ||
4188 | 0x1; | ||
4189 | } | ||
4190 | |||
4191 | /* | ||
4192 | * Set GPIO state | ||
4193 | */ | ||
4194 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | ||
4195 | { | ||
4196 | u32 data; | ||
4197 | ATH5K_TRACE(ah->ah_sc); | ||
4198 | |||
4199 | if (gpio > AR5K_NUM_GPIO) | ||
4200 | return -EINVAL; | ||
4201 | |||
4202 | /* GPIO output magic */ | ||
4203 | data = ath5k_hw_reg_read(ah, AR5K_GPIODO); | ||
4204 | |||
4205 | data &= ~(1 << gpio); | ||
4206 | data |= (val & 1) << gpio; | ||
4207 | |||
4208 | ath5k_hw_reg_write(ah, data, AR5K_GPIODO); | ||
4209 | |||
4210 | return 0; | ||
4211 | } | ||
4212 | |||
4213 | /* | ||
4214 | * Initialize the GPIO interrupt (RFKill switch) | ||
4215 | */ | ||
4216 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | ||
4217 | u32 interrupt_level) | ||
4218 | { | ||
4219 | u32 data; | ||
4220 | |||
4221 | ATH5K_TRACE(ah->ah_sc); | ||
4222 | if (gpio > AR5K_NUM_GPIO) | ||
4223 | return; | ||
4224 | |||
4225 | /* | ||
4226 | * Set the GPIO interrupt | ||
4227 | */ | ||
4228 | data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & | ||
4229 | ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | | ||
4230 | AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | | ||
4231 | (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); | ||
4232 | |||
4233 | ath5k_hw_reg_write(ah, interrupt_level ? data : | ||
4234 | (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); | ||
4235 | |||
4236 | ah->ah_imr |= AR5K_IMR_GPIO; | ||
4237 | |||
4238 | /* Enable GPIO interrupts */ | ||
4239 | AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); | ||
4240 | } | ||
4241 | |||
4242 | |||
4243 | /*********************************\ | ||
4244 | Regulatory Domain/Channels Setup | ||
4245 | \*********************************/ | ||
4246 | |||
4247 | u16 ath5k_get_regdomain(struct ath5k_hw *ah) | ||
4248 | { | ||
4249 | u16 regdomain; | ||
4250 | enum ath5k_regdom ieee_regdomain; | ||
4251 | #ifdef COUNTRYCODE | ||
4252 | u16 code; | ||
4253 | #endif | ||
4254 | |||
4255 | ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain); | ||
4256 | ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain; | ||
4257 | |||
4258 | #ifdef COUNTRYCODE | ||
4259 | /* | ||
4260 | * Get the regulation domain by country code. This will ignore | ||
4261 | * the settings found in the EEPROM. | ||
4262 | */ | ||
4263 | code = ieee80211_name2countrycode(COUNTRYCODE); | ||
4264 | ieee_regdomain = ieee80211_countrycode2regdomain(code); | ||
4265 | #endif | ||
4266 | |||
4267 | regdomain = ath5k_regdom_from_ieee(ieee_regdomain); | ||
4268 | ah->ah_capabilities.cap_regdomain.reg_current = regdomain; | ||
4269 | |||
4270 | return regdomain; | ||
4271 | } | ||
4272 | |||
4273 | |||
4274 | /****************\ | ||
4275 | Misc functions | ||
4276 | \****************/ | ||
4277 | |||
4278 | int ath5k_hw_get_capability(struct ath5k_hw *ah, | ||
4279 | enum ath5k_capability_type cap_type, | ||
4280 | u32 capability, u32 *result) | ||
4281 | { | ||
4282 | ATH5K_TRACE(ah->ah_sc); | ||
4283 | |||
4284 | switch (cap_type) { | ||
4285 | case AR5K_CAP_NUM_TXQUEUES: | ||
4286 | if (result) { | ||
4287 | if (ah->ah_version == AR5K_AR5210) | ||
4288 | *result = AR5K_NUM_TX_QUEUES_NOQCU; | ||
4289 | else | ||
4290 | *result = AR5K_NUM_TX_QUEUES; | ||
4291 | goto yes; | ||
4292 | } | ||
4293 | case AR5K_CAP_VEOL: | ||
4294 | goto yes; | ||
4295 | case AR5K_CAP_COMPRESSION: | ||
4296 | if (ah->ah_version == AR5K_AR5212) | ||
4297 | goto yes; | ||
4298 | else | ||
4299 | goto no; | ||
4300 | case AR5K_CAP_BURST: | ||
4301 | goto yes; | ||
4302 | case AR5K_CAP_TPC: | ||
4303 | goto yes; | ||
4304 | case AR5K_CAP_BSSIDMASK: | ||
4305 | if (ah->ah_version == AR5K_AR5212) | ||
4306 | goto yes; | ||
4307 | else | ||
4308 | goto no; | ||
4309 | case AR5K_CAP_XR: | ||
4310 | if (ah->ah_version == AR5K_AR5212) | ||
4311 | goto yes; | ||
4312 | else | ||
4313 | goto no; | ||
4314 | default: | ||
4315 | goto no; | ||
4316 | } | ||
4317 | |||
4318 | no: | ||
4319 | return -EINVAL; | ||
4320 | yes: | ||
4321 | return 0; | ||
4322 | } | ||
4323 | |||
4324 | static int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, | ||
4325 | u16 assoc_id) | ||
4326 | { | ||
4327 | ATH5K_TRACE(ah->ah_sc); | ||
4328 | |||
4329 | if (ah->ah_version == AR5K_AR5210) { | ||
4330 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
4331 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
4332 | return 0; | ||
4333 | } | ||
4334 | |||
4335 | return -EIO; | ||
4336 | } | ||
4337 | |||
4338 | static int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) | ||
4339 | { | ||
4340 | ATH5K_TRACE(ah->ah_sc); | ||
4341 | |||
4342 | if (ah->ah_version == AR5K_AR5210) { | ||
4343 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
4344 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | ||
4345 | return 0; | ||
4346 | } | ||
4347 | |||
4348 | return -EIO; | ||
4349 | } | ||
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h new file mode 100644 index 000000000000..d9a7c0973f53 --- /dev/null +++ b/drivers/net/wireless/ath5k/hw.h | |||
@@ -0,0 +1,588 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org> | ||
3 | * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com> | ||
4 | * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org> | ||
5 | * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | ||
6 | * | ||
7 | * Permission to use, copy, modify, and distribute this software for any | ||
8 | * purpose with or without fee is hereby granted, provided that the above | ||
9 | * copyright notice and this permission notice appear in all copies. | ||
10 | * | ||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | |||
22 | /* | ||
23 | * Gain settings | ||
24 | */ | ||
25 | |||
26 | enum ath5k_rfgain { | ||
27 | AR5K_RFGAIN_INACTIVE = 0, | ||
28 | AR5K_RFGAIN_READ_REQUESTED, | ||
29 | AR5K_RFGAIN_NEED_CHANGE, | ||
30 | }; | ||
31 | |||
32 | #define AR5K_GAIN_CRN_FIX_BITS_5111 4 | ||
33 | #define AR5K_GAIN_CRN_FIX_BITS_5112 7 | ||
34 | #define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 | ||
35 | #define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 | ||
36 | #define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 | ||
37 | #define AR5K_GAIN_CCK_PROBE_CORR 5 | ||
38 | #define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 | ||
39 | #define AR5K_GAIN_STEP_COUNT 10 | ||
40 | #define AR5K_GAIN_PARAM_TX_CLIP 0 | ||
41 | #define AR5K_GAIN_PARAM_PD_90 1 | ||
42 | #define AR5K_GAIN_PARAM_PD_84 2 | ||
43 | #define AR5K_GAIN_PARAM_GAIN_SEL 3 | ||
44 | #define AR5K_GAIN_PARAM_MIX_ORN 0 | ||
45 | #define AR5K_GAIN_PARAM_PD_138 1 | ||
46 | #define AR5K_GAIN_PARAM_PD_137 2 | ||
47 | #define AR5K_GAIN_PARAM_PD_136 3 | ||
48 | #define AR5K_GAIN_PARAM_PD_132 4 | ||
49 | #define AR5K_GAIN_PARAM_PD_131 5 | ||
50 | #define AR5K_GAIN_PARAM_PD_130 6 | ||
51 | #define AR5K_GAIN_CHECK_ADJUST(_g) \ | ||
52 | ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) | ||
53 | |||
54 | struct ath5k_gain_opt_step { | ||
55 | s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; | ||
56 | s32 gos_gain; | ||
57 | }; | ||
58 | |||
59 | struct ath5k_gain { | ||
60 | u32 g_step_idx; | ||
61 | u32 g_current; | ||
62 | u32 g_target; | ||
63 | u32 g_low; | ||
64 | u32 g_high; | ||
65 | u32 g_f_corr; | ||
66 | u32 g_active; | ||
67 | const struct ath5k_gain_opt_step *g_step; | ||
68 | }; | ||
69 | |||
70 | |||
71 | /* | ||
72 | * HW SPECIFIC STRUCTS | ||
73 | */ | ||
74 | |||
75 | /* Some EEPROM defines */ | ||
76 | #define AR5K_EEPROM_EEP_SCALE 100 | ||
77 | #define AR5K_EEPROM_EEP_DELTA 10 | ||
78 | #define AR5K_EEPROM_N_MODES 3 | ||
79 | #define AR5K_EEPROM_N_5GHZ_CHAN 10 | ||
80 | #define AR5K_EEPROM_N_2GHZ_CHAN 3 | ||
81 | #define AR5K_EEPROM_MAX_CHAN 10 | ||
82 | #define AR5K_EEPROM_N_PCDAC 11 | ||
83 | #define AR5K_EEPROM_N_TEST_FREQ 8 | ||
84 | #define AR5K_EEPROM_N_EDGES 8 | ||
85 | #define AR5K_EEPROM_N_INTERCEPTS 11 | ||
86 | #define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) | ||
87 | #define AR5K_EEPROM_PCDAC_M 0x3f | ||
88 | #define AR5K_EEPROM_PCDAC_START 1 | ||
89 | #define AR5K_EEPROM_PCDAC_STOP 63 | ||
90 | #define AR5K_EEPROM_PCDAC_STEP 1 | ||
91 | #define AR5K_EEPROM_NON_EDGE_M 0x40 | ||
92 | #define AR5K_EEPROM_CHANNEL_POWER 8 | ||
93 | #define AR5K_EEPROM_N_OBDB 4 | ||
94 | #define AR5K_EEPROM_OBDB_DIS 0xffff | ||
95 | #define AR5K_EEPROM_CHANNEL_DIS 0xff | ||
96 | #define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) | ||
97 | #define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) | ||
98 | #define AR5K_EEPROM_MAX_CTLS 32 | ||
99 | #define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 | ||
100 | #define AR5K_EEPROM_N_XPD0_POINTS 4 | ||
101 | #define AR5K_EEPROM_N_XPD3_POINTS 3 | ||
102 | #define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 | ||
103 | #define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 | ||
104 | #define AR5K_EEPROM_POWER_M 0x3f | ||
105 | #define AR5K_EEPROM_POWER_MIN 0 | ||
106 | #define AR5K_EEPROM_POWER_MAX 3150 | ||
107 | #define AR5K_EEPROM_POWER_STEP 50 | ||
108 | #define AR5K_EEPROM_POWER_TABLE_SIZE 64 | ||
109 | #define AR5K_EEPROM_N_POWER_LOC_11B 4 | ||
110 | #define AR5K_EEPROM_N_POWER_LOC_11G 6 | ||
111 | #define AR5K_EEPROM_I_GAIN 10 | ||
112 | #define AR5K_EEPROM_CCK_OFDM_DELTA 15 | ||
113 | #define AR5K_EEPROM_N_IQ_CAL 2 | ||
114 | |||
115 | /* Struct to hold EEPROM calibration data */ | ||
116 | struct ath5k_eeprom_info { | ||
117 | u16 ee_magic; | ||
118 | u16 ee_protect; | ||
119 | u16 ee_regdomain; | ||
120 | u16 ee_version; | ||
121 | u16 ee_header; | ||
122 | u16 ee_ant_gain; | ||
123 | u16 ee_misc0; | ||
124 | u16 ee_misc1; | ||
125 | u16 ee_cck_ofdm_gain_delta; | ||
126 | u16 ee_cck_ofdm_power_delta; | ||
127 | u16 ee_scaled_cck_delta; | ||
128 | |||
129 | /* Used for tx thermal adjustment (eeprom_init, rfregs) */ | ||
130 | u16 ee_tx_clip; | ||
131 | u16 ee_pwd_84; | ||
132 | u16 ee_pwd_90; | ||
133 | u16 ee_gain_select; | ||
134 | |||
135 | /* RF Calibration settings (reset, rfregs) */ | ||
136 | u16 ee_i_cal[AR5K_EEPROM_N_MODES]; | ||
137 | u16 ee_q_cal[AR5K_EEPROM_N_MODES]; | ||
138 | u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; | ||
139 | u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; | ||
140 | u16 ee_xr_power[AR5K_EEPROM_N_MODES]; | ||
141 | u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; | ||
142 | u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES]; | ||
143 | u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; | ||
144 | u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
145 | u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | ||
146 | u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; | ||
147 | u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; | ||
148 | u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; | ||
149 | u16 ee_thr_62[AR5K_EEPROM_N_MODES]; | ||
150 | u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; | ||
151 | u16 ee_xpd[AR5K_EEPROM_N_MODES]; | ||
152 | u16 ee_x_gain[AR5K_EEPROM_N_MODES]; | ||
153 | u16 ee_i_gain[AR5K_EEPROM_N_MODES]; | ||
154 | u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; | ||
155 | |||
156 | /* Unused */ | ||
157 | u16 ee_false_detect[AR5K_EEPROM_N_MODES]; | ||
158 | u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN]; | ||
159 | u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/ | ||
160 | |||
161 | /* Conformance test limits (Unused) */ | ||
162 | u16 ee_ctls; | ||
163 | u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; | ||
164 | |||
165 | /* Noise Floor Calibration settings */ | ||
166 | s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; | ||
167 | s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; | ||
168 | s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * Internal RX/TX descriptor structures | ||
173 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) | ||
174 | */ | ||
175 | |||
176 | struct ath5k_rx_desc { | ||
177 | u32 rx_control_0; /* RX control word 0 */ | ||
178 | |||
179 | #define AR5K_DESC_RX_CTL0 0x00000000 | ||
180 | |||
181 | u32 rx_control_1; /* RX control word 1 */ | ||
182 | |||
183 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff | ||
184 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 | ||
185 | } __packed; | ||
186 | |||
187 | /* | ||
188 | * 5210/5211 rx status descriptor | ||
189 | */ | ||
190 | struct ath5k_hw_old_rx_status { | ||
191 | u32 rx_status_0; /* RX status word 0 */ | ||
192 | |||
193 | #define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
194 | #define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000 | ||
195 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | ||
196 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
197 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 | ||
198 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | ||
199 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | ||
200 | #define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | ||
201 | |||
202 | u32 rx_status_1; /* RX status word 1 */ | ||
203 | |||
204 | #define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001 | ||
205 | #define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
206 | #define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
207 | #define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 | ||
208 | #define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 | ||
209 | #define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 | ||
210 | #define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5 | ||
211 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
212 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 | ||
213 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
214 | #define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 | ||
215 | #define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 | ||
216 | #define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | ||
217 | } __packed; | ||
218 | |||
219 | /* | ||
220 | * 5212 rx status descriptor | ||
221 | */ | ||
222 | struct ath5k_hw_new_rx_status { | ||
223 | u32 rx_status_0; /* RX status word 0 */ | ||
224 | |||
225 | #define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff | ||
226 | #define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000 | ||
227 | #define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | ||
228 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 | ||
229 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | ||
230 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 | ||
231 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | ||
232 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | ||
233 | #define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | ||
234 | |||
235 | u32 rx_status_1; /* RX status word 1 */ | ||
236 | |||
237 | #define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001 | ||
238 | #define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | ||
239 | #define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | ||
240 | #define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 | ||
241 | #define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010 | ||
242 | #define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020 | ||
243 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | ||
244 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 | ||
245 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9 | ||
246 | #define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 | ||
247 | #define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 | ||
248 | #define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 | ||
249 | } __packed; | ||
250 | |||
251 | struct ath5k_hw_rx_error { | ||
252 | u32 rx_error_0; /* RX error word 0 */ | ||
253 | |||
254 | #define AR5K_RX_DESC_ERROR0 0x00000000 | ||
255 | |||
256 | u32 rx_error_1; /* RX error word 1 */ | ||
257 | |||
258 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | ||
259 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | ||
260 | } __packed; | ||
261 | |||
262 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 | ||
263 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 | ||
264 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 | ||
265 | #define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 | ||
266 | #define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 | ||
267 | #define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 | ||
268 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 | ||
269 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 | ||
270 | |||
271 | struct ath5k_hw_2w_tx_desc { | ||
272 | u32 tx_control_0; /* TX control word 0 */ | ||
273 | |||
274 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | ||
275 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ | ||
276 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 | ||
277 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 | ||
278 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 | ||
279 | #define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 | ||
280 | #define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 | ||
281 | #define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ | ||
282 | #define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ | ||
283 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ | ||
284 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 | ||
285 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 | ||
286 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 | ||
287 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT (ah->ah_version == AR5K_AR5210 ? \ | ||
288 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ | ||
289 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) | ||
290 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | ||
291 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 | ||
292 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | ||
293 | |||
294 | u32 tx_control_1; /* TX control word 1 */ | ||
295 | |||
296 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff | ||
297 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 | ||
298 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 | ||
299 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 | ||
300 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX (ah->ah_version == AR5K_AR5210 ? \ | ||
301 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ | ||
302 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) | ||
303 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | ||
304 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ | ||
305 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 | ||
306 | #define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ | ||
307 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ | ||
308 | } __packed; | ||
309 | |||
310 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 | ||
311 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 | ||
312 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 | ||
313 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c | ||
314 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 | ||
315 | |||
316 | /* | ||
317 | * 5212 4-word tx control descriptor | ||
318 | */ | ||
319 | struct ath5k_hw_4w_tx_desc { | ||
320 | u32 tx_control_0; /* TX control word 0 */ | ||
321 | |||
322 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | ||
323 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 | ||
324 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 | ||
325 | #define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 | ||
326 | #define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 | ||
327 | #define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 | ||
328 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 | ||
329 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | ||
330 | #define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 | ||
331 | #define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | ||
332 | #define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 | ||
333 | |||
334 | u32 tx_control_1; /* TX control word 1 */ | ||
335 | |||
336 | #define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff | ||
337 | #define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 | ||
338 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 | ||
339 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | ||
340 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 | ||
341 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 | ||
342 | #define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 | ||
343 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 | ||
344 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 | ||
345 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 | ||
346 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 | ||
347 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 | ||
348 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 | ||
349 | |||
350 | u32 tx_control_2; /* TX control word 2 */ | ||
351 | |||
352 | #define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff | ||
353 | #define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 | ||
354 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 | ||
355 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 | ||
356 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 | ||
357 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 | ||
358 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 | ||
359 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 | ||
360 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 | ||
361 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 | ||
362 | |||
363 | u32 tx_control_3; /* TX control word 3 */ | ||
364 | |||
365 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f | ||
366 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 | ||
367 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 | ||
368 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 | ||
369 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 | ||
370 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 | ||
371 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 | ||
372 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 | ||
373 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 | ||
374 | } __packed; | ||
375 | |||
376 | /* | ||
377 | * Common tx status descriptor | ||
378 | */ | ||
379 | struct ath5k_hw_tx_status { | ||
380 | u32 tx_status_0; /* TX status word 0 */ | ||
381 | |||
382 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 | ||
383 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 | ||
384 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 | ||
385 | #define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 | ||
386 | /*??? | ||
387 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 | ||
388 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 | ||
389 | */ | ||
390 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 | ||
391 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 | ||
392 | /*??? | ||
393 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 | ||
394 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 | ||
395 | */ | ||
396 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 | ||
397 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 | ||
398 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 | ||
399 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 | ||
400 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 | ||
401 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 | ||
402 | |||
403 | u32 tx_status_1; /* TX status word 1 */ | ||
404 | |||
405 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 | ||
406 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe | ||
407 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 | ||
408 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 | ||
409 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 | ||
410 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 | ||
411 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 | ||
412 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 | ||
413 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 | ||
414 | } __packed; | ||
415 | |||
416 | |||
417 | /* | ||
418 | * AR5K REGISTER ACCESS | ||
419 | */ | ||
420 | |||
421 | /*Swap RX/TX Descriptor for big endian archs*/ | ||
422 | #if defined(__BIG_ENDIAN) | ||
423 | #define AR5K_INIT_CFG ( \ | ||
424 | AR5K_CFG_SWTD | AR5K_CFG_SWRD \ | ||
425 | ) | ||
426 | #else | ||
427 | #define AR5K_INIT_CFG 0x00000000 | ||
428 | #endif | ||
429 | |||
430 | /*#define AR5K_REG_READ(_reg) ath5k_hw_reg_read(ah, _reg) | ||
431 | |||
432 | #define AR5K_REG_WRITE(_reg, _val) ath5k_hw_reg_write(ah, _val, _reg)*/ | ||
433 | |||
434 | #define AR5K_REG_SM(_val, _flags) \ | ||
435 | (((_val) << _flags##_S) & (_flags)) | ||
436 | |||
437 | #define AR5K_REG_MS(_val, _flags) \ | ||
438 | (((_val) & (_flags)) >> _flags##_S) | ||
439 | |||
440 | /* Some registers can hold multiple values of interest. For this | ||
441 | * reason when we want to write to these registers we must first | ||
442 | * retrieve the values which we do not want to clear (lets call this | ||
443 | * old_data) and then set the register with this and our new_value: | ||
444 | * ( old_data | new_value) */ | ||
445 | #define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ | ||
446 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ | ||
447 | (((_val) << _flags##_S) & (_flags)), _reg) | ||
448 | |||
449 | #define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ | ||
450 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ | ||
451 | (_mask)) | (_flags), _reg) | ||
452 | |||
453 | #define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ | ||
454 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) | ||
455 | |||
456 | #define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ | ||
457 | ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) | ||
458 | |||
459 | #define AR5K_PHY_WRITE(ah, _reg, _val) \ | ||
460 | ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) | ||
461 | |||
462 | #define AR5K_PHY_READ(ah, _reg) \ | ||
463 | ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) | ||
464 | |||
465 | #define AR5K_REG_WAIT(_i) do { \ | ||
466 | if (_i % 64) \ | ||
467 | udelay(1); \ | ||
468 | } while (0) | ||
469 | |||
470 | #define AR5K_EEPROM_READ(_o, _v) do { \ | ||
471 | if ((ret = ath5k_hw_eeprom_read(ah, (_o), &(_v))) != 0) \ | ||
472 | return (ret); \ | ||
473 | } while (0) | ||
474 | |||
475 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | ||
476 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ | ||
477 | |||
478 | /* Read status of selected queue */ | ||
479 | #define AR5K_REG_READ_Q(ah, _reg, _queue) \ | ||
480 | (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ | ||
481 | |||
482 | #define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ | ||
483 | ath5k_hw_reg_write(ah, (1 << _queue), _reg) | ||
484 | |||
485 | #define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ | ||
486 | _reg |= 1 << _queue; \ | ||
487 | } while (0) | ||
488 | |||
489 | #define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ | ||
490 | _reg &= ~(1 << _queue); \ | ||
491 | } while (0) | ||
492 | |||
493 | #define AR5K_LOW_ID(_a)( \ | ||
494 | (_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ | ||
495 | ) | ||
496 | |||
497 | #define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) | ||
498 | |||
499 | /* | ||
500 | * Initial register values | ||
501 | */ | ||
502 | |||
503 | /* | ||
504 | * Common initial register values | ||
505 | */ | ||
506 | #define AR5K_INIT_MODE CHANNEL_B | ||
507 | |||
508 | #define AR5K_INIT_TX_LATENCY 502 | ||
509 | #define AR5K_INIT_USEC 39 | ||
510 | #define AR5K_INIT_USEC_TURBO 79 | ||
511 | #define AR5K_INIT_USEC_32 31 | ||
512 | #define AR5K_INIT_CARR_SENSE_EN 1 | ||
513 | #define AR5K_INIT_PROG_IFS 920 | ||
514 | #define AR5K_INIT_PROG_IFS_TURBO 960 | ||
515 | #define AR5K_INIT_EIFS 3440 | ||
516 | #define AR5K_INIT_EIFS_TURBO 6880 | ||
517 | #define AR5K_INIT_SLOT_TIME 396 | ||
518 | #define AR5K_INIT_SLOT_TIME_TURBO 480 | ||
519 | #define AR5K_INIT_ACK_CTS_TIMEOUT 1024 | ||
520 | #define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 | ||
521 | #define AR5K_INIT_SIFS 560 | ||
522 | #define AR5K_INIT_SIFS_TURBO 480 | ||
523 | #define AR5K_INIT_SH_RETRY 10 | ||
524 | #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY | ||
525 | #define AR5K_INIT_SSH_RETRY 32 | ||
526 | #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY | ||
527 | #define AR5K_INIT_TX_RETRY 10 | ||
528 | #define AR5K_INIT_TOPS 8 | ||
529 | #define AR5K_INIT_RXNOFRM 8 | ||
530 | #define AR5K_INIT_RPGTO 0 | ||
531 | #define AR5K_INIT_TXNOFRM 0 | ||
532 | #define AR5K_INIT_BEACON_PERIOD 65535 | ||
533 | #define AR5K_INIT_TIM_OFFSET 0 | ||
534 | #define AR5K_INIT_BEACON_EN 0 | ||
535 | #define AR5K_INIT_RESET_TSF 0 | ||
536 | |||
537 | #define AR5K_INIT_TRANSMIT_LATENCY ( \ | ||
538 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
539 | (AR5K_INIT_USEC) \ | ||
540 | ) | ||
541 | #define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ | ||
542 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
543 | (AR5K_INIT_USEC_TURBO) \ | ||
544 | ) | ||
545 | #define AR5K_INIT_PROTO_TIME_CNTRL ( \ | ||
546 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ | ||
547 | (AR5K_INIT_PROG_IFS) \ | ||
548 | ) | ||
549 | #define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ | ||
550 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ | ||
551 | (AR5K_INIT_PROG_IFS_TURBO) \ | ||
552 | ) | ||
553 | #define AR5K_INIT_BEACON_CONTROL ( \ | ||
554 | (AR5K_INIT_RESET_TSF << 24) | (AR5K_INIT_BEACON_EN << 23) | \ | ||
555 | (AR5K_INIT_TIM_OFFSET << 16) | (AR5K_INIT_BEACON_PERIOD) \ | ||
556 | ) | ||
557 | |||
558 | /* | ||
559 | * Non-common initial register values which have to be loaded into the | ||
560 | * card at boot time and after each reset. | ||
561 | */ | ||
562 | |||
563 | /* Register dumps are done per operation mode */ | ||
564 | #define AR5K_INI_RFGAIN_5GHZ 0 | ||
565 | #define AR5K_INI_RFGAIN_2GHZ 1 | ||
566 | |||
567 | #define AR5K_INI_VAL_11A 0 | ||
568 | #define AR5K_INI_VAL_11A_TURBO 1 | ||
569 | #define AR5K_INI_VAL_11B 2 | ||
570 | #define AR5K_INI_VAL_11G 3 | ||
571 | #define AR5K_INI_VAL_11G_TURBO 4 | ||
572 | #define AR5K_INI_VAL_XR 0 | ||
573 | #define AR5K_INI_VAL_MAX 5 | ||
574 | |||
575 | #define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
576 | #define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS | ||
577 | |||
578 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | ||
579 | { | ||
580 | u32 retval = 0, bit, i; | ||
581 | |||
582 | for (i = 0; i < bits; i++) { | ||
583 | bit = (val >> i) & 1; | ||
584 | retval = (retval << 1) | bit; | ||
585 | } | ||
586 | |||
587 | return retval; | ||
588 | } | ||
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c new file mode 100644 index 000000000000..2c22f1d4ee64 --- /dev/null +++ b/drivers/net/wireless/ath5k/initvals.c | |||
@@ -0,0 +1,1347 @@ | |||
1 | /* | ||
2 | * Initial register settings functions | ||
3 | * | ||
4 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | ||
5 | * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com> | ||
6 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "ath5k.h" | ||
23 | #include "base.h" | ||
24 | #include "reg.h" | ||
25 | |||
26 | /* | ||
27 | * MAC/PHY REGISTERS | ||
28 | */ | ||
29 | |||
30 | |||
31 | /* | ||
32 | * Mode-independent initial register writes | ||
33 | */ | ||
34 | |||
35 | struct ath5k_ini { | ||
36 | u16 ini_register; | ||
37 | u32 ini_value; | ||
38 | |||
39 | enum { | ||
40 | AR5K_INI_WRITE = 0, /* Default */ | ||
41 | AR5K_INI_READ = 1, /* Cleared on read */ | ||
42 | } ini_mode; | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * Mode specific initial register values | ||
47 | */ | ||
48 | |||
49 | struct ath5k_ini_mode { | ||
50 | u16 mode_register; | ||
51 | u32 mode_value[5]; | ||
52 | }; | ||
53 | |||
54 | /* Initial register settings for AR5210 */ | ||
55 | static const struct ath5k_ini ar5210_ini[] = { | ||
56 | /* PCU and MAC registers */ | ||
57 | { AR5K_NOQCU_TXDP0, 0 }, | ||
58 | { AR5K_NOQCU_TXDP1, 0 }, | ||
59 | { AR5K_RXDP, 0 }, | ||
60 | { AR5K_CR, 0 }, | ||
61 | { AR5K_ISR, 0, AR5K_INI_READ }, | ||
62 | { AR5K_IMR, 0 }, | ||
63 | { AR5K_IER, AR5K_IER_DISABLE }, | ||
64 | { AR5K_BSR, 0, AR5K_INI_READ }, | ||
65 | { AR5K_TXCFG, AR5K_DMASIZE_128B }, | ||
66 | { AR5K_RXCFG, AR5K_DMASIZE_128B }, | ||
67 | { AR5K_CFG, AR5K_INIT_CFG }, | ||
68 | { AR5K_TOPS, AR5K_INIT_TOPS }, | ||
69 | { AR5K_RXNOFRM, AR5K_INIT_RXNOFRM }, | ||
70 | { AR5K_RPGTO, AR5K_INIT_RPGTO }, | ||
71 | { AR5K_TXNOFRM, AR5K_INIT_TXNOFRM }, | ||
72 | { AR5K_SFR, 0 }, | ||
73 | { AR5K_MIBC, 0 }, | ||
74 | { AR5K_MISC, 0 }, | ||
75 | { AR5K_RX_FILTER_5210, 0 }, | ||
76 | { AR5K_MCAST_FILTER0_5210, 0 }, | ||
77 | { AR5K_MCAST_FILTER1_5210, 0 }, | ||
78 | { AR5K_TX_MASK0, 0 }, | ||
79 | { AR5K_TX_MASK1, 0 }, | ||
80 | { AR5K_CLR_TMASK, 0 }, | ||
81 | { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES }, | ||
82 | { AR5K_DIAG_SW_5210, 0 }, | ||
83 | { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES }, | ||
84 | { AR5K_TSF_L32_5210, 0 }, | ||
85 | { AR5K_TIMER0_5210, 0 }, | ||
86 | { AR5K_TIMER1_5210, 0xffffffff }, | ||
87 | { AR5K_TIMER2_5210, 0xffffffff }, | ||
88 | { AR5K_TIMER3_5210, 1 }, | ||
89 | { AR5K_CFP_DUR_5210, 0 }, | ||
90 | { AR5K_CFP_PERIOD_5210, 0 }, | ||
91 | /* PHY registers */ | ||
92 | { AR5K_PHY(0), 0x00000047 }, | ||
93 | { AR5K_PHY_AGC, 0x00000000 }, | ||
94 | { AR5K_PHY(3), 0x09848ea6 }, | ||
95 | { AR5K_PHY(4), 0x3d32e000 }, | ||
96 | { AR5K_PHY(5), 0x0000076b }, | ||
97 | { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE }, | ||
98 | { AR5K_PHY(8), 0x02020200 }, | ||
99 | { AR5K_PHY(9), 0x00000e0e }, | ||
100 | { AR5K_PHY(10), 0x0a020201 }, | ||
101 | { AR5K_PHY(11), 0x00036ffc }, | ||
102 | { AR5K_PHY(12), 0x00000000 }, | ||
103 | { AR5K_PHY(13), 0x00000e0e }, | ||
104 | { AR5K_PHY(14), 0x00000007 }, | ||
105 | { AR5K_PHY(15), 0x00020100 }, | ||
106 | { AR5K_PHY(16), 0x89630000 }, | ||
107 | { AR5K_PHY(17), 0x1372169c }, | ||
108 | { AR5K_PHY(18), 0x0018b633 }, | ||
109 | { AR5K_PHY(19), 0x1284613c }, | ||
110 | { AR5K_PHY(20), 0x0de8b8e0 }, | ||
111 | { AR5K_PHY(21), 0x00074859 }, | ||
112 | { AR5K_PHY(22), 0x7e80beba }, | ||
113 | { AR5K_PHY(23), 0x313a665e }, | ||
114 | { AR5K_PHY_AGCCTL, 0x00001d08 }, | ||
115 | { AR5K_PHY(25), 0x0001ce00 }, | ||
116 | { AR5K_PHY(26), 0x409a4190 }, | ||
117 | { AR5K_PHY(28), 0x0000000f }, | ||
118 | { AR5K_PHY(29), 0x00000080 }, | ||
119 | { AR5K_PHY(30), 0x00000004 }, | ||
120 | { AR5K_PHY(31), 0x00000018 }, /* 0x987c */ | ||
121 | { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */ | ||
122 | { AR5K_PHY(65), 0x00000000 }, | ||
123 | { AR5K_PHY(66), 0x00000000 }, | ||
124 | { AR5K_PHY(67), 0x00800000 }, | ||
125 | { AR5K_PHY(68), 0x00000003 }, | ||
126 | /* BB gain table (64bytes) */ | ||
127 | { AR5K_BB_GAIN(0), 0x00000000 }, | ||
128 | { AR5K_BB_GAIN(1), 0x00000020 }, | ||
129 | { AR5K_BB_GAIN(2), 0x00000010 }, | ||
130 | { AR5K_BB_GAIN(3), 0x00000030 }, | ||
131 | { AR5K_BB_GAIN(4), 0x00000008 }, | ||
132 | { AR5K_BB_GAIN(5), 0x00000028 }, | ||
133 | { AR5K_BB_GAIN(6), 0x00000028 }, | ||
134 | { AR5K_BB_GAIN(7), 0x00000004 }, | ||
135 | { AR5K_BB_GAIN(8), 0x00000024 }, | ||
136 | { AR5K_BB_GAIN(9), 0x00000014 }, | ||
137 | { AR5K_BB_GAIN(10), 0x00000034 }, | ||
138 | { AR5K_BB_GAIN(11), 0x0000000c }, | ||
139 | { AR5K_BB_GAIN(12), 0x0000002c }, | ||
140 | { AR5K_BB_GAIN(13), 0x00000002 }, | ||
141 | { AR5K_BB_GAIN(14), 0x00000022 }, | ||
142 | { AR5K_BB_GAIN(15), 0x00000012 }, | ||
143 | { AR5K_BB_GAIN(16), 0x00000032 }, | ||
144 | { AR5K_BB_GAIN(17), 0x0000000a }, | ||
145 | { AR5K_BB_GAIN(18), 0x0000002a }, | ||
146 | { AR5K_BB_GAIN(19), 0x00000001 }, | ||
147 | { AR5K_BB_GAIN(20), 0x00000021 }, | ||
148 | { AR5K_BB_GAIN(21), 0x00000011 }, | ||
149 | { AR5K_BB_GAIN(22), 0x00000031 }, | ||
150 | { AR5K_BB_GAIN(23), 0x00000009 }, | ||
151 | { AR5K_BB_GAIN(24), 0x00000029 }, | ||
152 | { AR5K_BB_GAIN(25), 0x00000005 }, | ||
153 | { AR5K_BB_GAIN(26), 0x00000025 }, | ||
154 | { AR5K_BB_GAIN(27), 0x00000015 }, | ||
155 | { AR5K_BB_GAIN(28), 0x00000035 }, | ||
156 | { AR5K_BB_GAIN(29), 0x0000000d }, | ||
157 | { AR5K_BB_GAIN(30), 0x0000002d }, | ||
158 | { AR5K_BB_GAIN(31), 0x00000003 }, | ||
159 | { AR5K_BB_GAIN(32), 0x00000023 }, | ||
160 | { AR5K_BB_GAIN(33), 0x00000013 }, | ||
161 | { AR5K_BB_GAIN(34), 0x00000033 }, | ||
162 | { AR5K_BB_GAIN(35), 0x0000000b }, | ||
163 | { AR5K_BB_GAIN(36), 0x0000002b }, | ||
164 | { AR5K_BB_GAIN(37), 0x00000007 }, | ||
165 | { AR5K_BB_GAIN(38), 0x00000027 }, | ||
166 | { AR5K_BB_GAIN(39), 0x00000017 }, | ||
167 | { AR5K_BB_GAIN(40), 0x00000037 }, | ||
168 | { AR5K_BB_GAIN(41), 0x0000000f }, | ||
169 | { AR5K_BB_GAIN(42), 0x0000002f }, | ||
170 | { AR5K_BB_GAIN(43), 0x0000002f }, | ||
171 | { AR5K_BB_GAIN(44), 0x0000002f }, | ||
172 | { AR5K_BB_GAIN(45), 0x0000002f }, | ||
173 | { AR5K_BB_GAIN(46), 0x0000002f }, | ||
174 | { AR5K_BB_GAIN(47), 0x0000002f }, | ||
175 | { AR5K_BB_GAIN(48), 0x0000002f }, | ||
176 | { AR5K_BB_GAIN(49), 0x0000002f }, | ||
177 | { AR5K_BB_GAIN(50), 0x0000002f }, | ||
178 | { AR5K_BB_GAIN(51), 0x0000002f }, | ||
179 | { AR5K_BB_GAIN(52), 0x0000002f }, | ||
180 | { AR5K_BB_GAIN(53), 0x0000002f }, | ||
181 | { AR5K_BB_GAIN(54), 0x0000002f }, | ||
182 | { AR5K_BB_GAIN(55), 0x0000002f }, | ||
183 | { AR5K_BB_GAIN(56), 0x0000002f }, | ||
184 | { AR5K_BB_GAIN(57), 0x0000002f }, | ||
185 | { AR5K_BB_GAIN(58), 0x0000002f }, | ||
186 | { AR5K_BB_GAIN(59), 0x0000002f }, | ||
187 | { AR5K_BB_GAIN(60), 0x0000002f }, | ||
188 | { AR5K_BB_GAIN(61), 0x0000002f }, | ||
189 | { AR5K_BB_GAIN(62), 0x0000002f }, | ||
190 | { AR5K_BB_GAIN(63), 0x0000002f }, | ||
191 | /* 5110 RF gain table (64btes) */ | ||
192 | { AR5K_RF_GAIN(0), 0x0000001d }, | ||
193 | { AR5K_RF_GAIN(1), 0x0000005d }, | ||
194 | { AR5K_RF_GAIN(2), 0x0000009d }, | ||
195 | { AR5K_RF_GAIN(3), 0x000000dd }, | ||
196 | { AR5K_RF_GAIN(4), 0x0000011d }, | ||
197 | { AR5K_RF_GAIN(5), 0x00000021 }, | ||
198 | { AR5K_RF_GAIN(6), 0x00000061 }, | ||
199 | { AR5K_RF_GAIN(7), 0x000000a1 }, | ||
200 | { AR5K_RF_GAIN(8), 0x000000e1 }, | ||
201 | { AR5K_RF_GAIN(9), 0x00000031 }, | ||
202 | { AR5K_RF_GAIN(10), 0x00000071 }, | ||
203 | { AR5K_RF_GAIN(11), 0x000000b1 }, | ||
204 | { AR5K_RF_GAIN(12), 0x0000001c }, | ||
205 | { AR5K_RF_GAIN(13), 0x0000005c }, | ||
206 | { AR5K_RF_GAIN(14), 0x00000029 }, | ||
207 | { AR5K_RF_GAIN(15), 0x00000069 }, | ||
208 | { AR5K_RF_GAIN(16), 0x000000a9 }, | ||
209 | { AR5K_RF_GAIN(17), 0x00000020 }, | ||
210 | { AR5K_RF_GAIN(18), 0x00000019 }, | ||
211 | { AR5K_RF_GAIN(19), 0x00000059 }, | ||
212 | { AR5K_RF_GAIN(20), 0x00000099 }, | ||
213 | { AR5K_RF_GAIN(21), 0x00000030 }, | ||
214 | { AR5K_RF_GAIN(22), 0x00000005 }, | ||
215 | { AR5K_RF_GAIN(23), 0x00000025 }, | ||
216 | { AR5K_RF_GAIN(24), 0x00000065 }, | ||
217 | { AR5K_RF_GAIN(25), 0x000000a5 }, | ||
218 | { AR5K_RF_GAIN(26), 0x00000028 }, | ||
219 | { AR5K_RF_GAIN(27), 0x00000068 }, | ||
220 | { AR5K_RF_GAIN(28), 0x0000001f }, | ||
221 | { AR5K_RF_GAIN(29), 0x0000001e }, | ||
222 | { AR5K_RF_GAIN(30), 0x00000018 }, | ||
223 | { AR5K_RF_GAIN(31), 0x00000058 }, | ||
224 | { AR5K_RF_GAIN(32), 0x00000098 }, | ||
225 | { AR5K_RF_GAIN(33), 0x00000003 }, | ||
226 | { AR5K_RF_GAIN(34), 0x00000004 }, | ||
227 | { AR5K_RF_GAIN(35), 0x00000044 }, | ||
228 | { AR5K_RF_GAIN(36), 0x00000084 }, | ||
229 | { AR5K_RF_GAIN(37), 0x00000013 }, | ||
230 | { AR5K_RF_GAIN(38), 0x00000012 }, | ||
231 | { AR5K_RF_GAIN(39), 0x00000052 }, | ||
232 | { AR5K_RF_GAIN(40), 0x00000092 }, | ||
233 | { AR5K_RF_GAIN(41), 0x000000d2 }, | ||
234 | { AR5K_RF_GAIN(42), 0x0000002b }, | ||
235 | { AR5K_RF_GAIN(43), 0x0000002a }, | ||
236 | { AR5K_RF_GAIN(44), 0x0000006a }, | ||
237 | { AR5K_RF_GAIN(45), 0x000000aa }, | ||
238 | { AR5K_RF_GAIN(46), 0x0000001b }, | ||
239 | { AR5K_RF_GAIN(47), 0x0000001a }, | ||
240 | { AR5K_RF_GAIN(48), 0x0000005a }, | ||
241 | { AR5K_RF_GAIN(49), 0x0000009a }, | ||
242 | { AR5K_RF_GAIN(50), 0x000000da }, | ||
243 | { AR5K_RF_GAIN(51), 0x00000006 }, | ||
244 | { AR5K_RF_GAIN(52), 0x00000006 }, | ||
245 | { AR5K_RF_GAIN(53), 0x00000006 }, | ||
246 | { AR5K_RF_GAIN(54), 0x00000006 }, | ||
247 | { AR5K_RF_GAIN(55), 0x00000006 }, | ||
248 | { AR5K_RF_GAIN(56), 0x00000006 }, | ||
249 | { AR5K_RF_GAIN(57), 0x00000006 }, | ||
250 | { AR5K_RF_GAIN(58), 0x00000006 }, | ||
251 | { AR5K_RF_GAIN(59), 0x00000006 }, | ||
252 | { AR5K_RF_GAIN(60), 0x00000006 }, | ||
253 | { AR5K_RF_GAIN(61), 0x00000006 }, | ||
254 | { AR5K_RF_GAIN(62), 0x00000006 }, | ||
255 | { AR5K_RF_GAIN(63), 0x00000006 }, | ||
256 | /* PHY activation */ | ||
257 | { AR5K_PHY(53), 0x00000020 }, | ||
258 | { AR5K_PHY(51), 0x00000004 }, | ||
259 | { AR5K_PHY(50), 0x00060106 }, | ||
260 | { AR5K_PHY(39), 0x0000006d }, | ||
261 | { AR5K_PHY(48), 0x00000000 }, | ||
262 | { AR5K_PHY(52), 0x00000014 }, | ||
263 | { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE }, | ||
264 | }; | ||
265 | |||
266 | /* Initial register settings for AR5211 */ | ||
267 | static const struct ath5k_ini ar5211_ini[] = { | ||
268 | { AR5K_RXDP, 0x00000000 }, | ||
269 | { AR5K_RTSD0, 0x84849c9c }, | ||
270 | { AR5K_RTSD1, 0x7c7c7c7c }, | ||
271 | { AR5K_RXCFG, 0x00000005 }, | ||
272 | { AR5K_MIBC, 0x00000000 }, | ||
273 | { AR5K_TOPS, 0x00000008 }, | ||
274 | { AR5K_RXNOFRM, 0x00000008 }, | ||
275 | { AR5K_TXNOFRM, 0x00000010 }, | ||
276 | { AR5K_RPGTO, 0x00000000 }, | ||
277 | { AR5K_RFCNT, 0x0000001f }, | ||
278 | { AR5K_QUEUE_TXDP(0), 0x00000000 }, | ||
279 | { AR5K_QUEUE_TXDP(1), 0x00000000 }, | ||
280 | { AR5K_QUEUE_TXDP(2), 0x00000000 }, | ||
281 | { AR5K_QUEUE_TXDP(3), 0x00000000 }, | ||
282 | { AR5K_QUEUE_TXDP(4), 0x00000000 }, | ||
283 | { AR5K_QUEUE_TXDP(5), 0x00000000 }, | ||
284 | { AR5K_QUEUE_TXDP(6), 0x00000000 }, | ||
285 | { AR5K_QUEUE_TXDP(7), 0x00000000 }, | ||
286 | { AR5K_QUEUE_TXDP(8), 0x00000000 }, | ||
287 | { AR5K_QUEUE_TXDP(9), 0x00000000 }, | ||
288 | { AR5K_DCU_FP, 0x00000000 }, | ||
289 | { AR5K_STA_ID1, 0x00000000 }, | ||
290 | { AR5K_BSS_ID0, 0x00000000 }, | ||
291 | { AR5K_BSS_ID1, 0x00000000 }, | ||
292 | { AR5K_RSSI_THR, 0x00000000 }, | ||
293 | { AR5K_CFP_PERIOD_5211, 0x00000000 }, | ||
294 | { AR5K_TIMER0_5211, 0x00000030 }, | ||
295 | { AR5K_TIMER1_5211, 0x0007ffff }, | ||
296 | { AR5K_TIMER2_5211, 0x01ffffff }, | ||
297 | { AR5K_TIMER3_5211, 0x00000031 }, | ||
298 | { AR5K_CFP_DUR_5211, 0x00000000 }, | ||
299 | { AR5K_RX_FILTER_5211, 0x00000000 }, | ||
300 | { AR5K_MCAST_FILTER0_5211, 0x00000000 }, | ||
301 | { AR5K_MCAST_FILTER1_5211, 0x00000002 }, | ||
302 | { AR5K_DIAG_SW_5211, 0x00000000 }, | ||
303 | { AR5K_ADDAC_TEST, 0x00000000 }, | ||
304 | { AR5K_DEFAULT_ANTENNA, 0x00000000 }, | ||
305 | /* PHY registers */ | ||
306 | { AR5K_PHY_AGC, 0x00000000 }, | ||
307 | { AR5K_PHY(3), 0x2d849093 }, | ||
308 | { AR5K_PHY(4), 0x7d32e000 }, | ||
309 | { AR5K_PHY(5), 0x00000f6b }, | ||
310 | { AR5K_PHY_ACT, 0x00000000 }, | ||
311 | { AR5K_PHY(11), 0x00026ffe }, | ||
312 | { AR5K_PHY(12), 0x00000000 }, | ||
313 | { AR5K_PHY(15), 0x00020100 }, | ||
314 | { AR5K_PHY(16), 0x206a017a }, | ||
315 | { AR5K_PHY(19), 0x1284613c }, | ||
316 | { AR5K_PHY(21), 0x00000859 }, | ||
317 | { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */ | ||
318 | { AR5K_PHY(27), 0x050cb081 }, | ||
319 | { AR5K_PHY(28), 0x0000000f }, | ||
320 | { AR5K_PHY(29), 0x00000080 }, | ||
321 | { AR5K_PHY(30), 0x0000000c }, | ||
322 | { AR5K_PHY(64), 0x00000000 }, | ||
323 | { AR5K_PHY(65), 0x00000000 }, | ||
324 | { AR5K_PHY(66), 0x00000000 }, | ||
325 | { AR5K_PHY(67), 0x00800000 }, | ||
326 | { AR5K_PHY(68), 0x00000001 }, | ||
327 | { AR5K_PHY(71), 0x0000092a }, | ||
328 | { AR5K_PHY_IQ, 0x00000000 }, | ||
329 | { AR5K_PHY(73), 0x00058a05 }, | ||
330 | { AR5K_PHY(74), 0x00000001 }, | ||
331 | { AR5K_PHY(75), 0x00000000 }, | ||
332 | { AR5K_PHY_PAPD_PROBE, 0x00000000 }, | ||
333 | { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */ | ||
334 | { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */ | ||
335 | { AR5K_PHY(79), 0x0000003f }, /* 0x993c */ | ||
336 | { AR5K_PHY(80), 0x00000004 }, | ||
337 | { AR5K_PHY(82), 0x00000000 }, | ||
338 | { AR5K_PHY(83), 0x00000000 }, | ||
339 | { AR5K_PHY(84), 0x00000000 }, | ||
340 | { AR5K_PHY_RADAR, 0x5d50f14c }, | ||
341 | { AR5K_PHY(86), 0x00000018 }, | ||
342 | { AR5K_PHY(87), 0x004b6a8e }, | ||
343 | /* Initial Power table (32bytes) | ||
344 | * common on all cards/modes. | ||
345 | * Note: Table is rewritten during | ||
346 | * txpower setup later using calibration | ||
347 | * data etc. so next write is non-common | ||
348 | { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff }, | ||
349 | { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff }, | ||
350 | { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff }, | ||
351 | { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff }, | ||
352 | { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff }, | ||
353 | { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff }, | ||
354 | { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff }, | ||
355 | { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff }, | ||
356 | { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff }, | ||
357 | { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff }, | ||
358 | { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff }, | ||
359 | { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff }, | ||
360 | { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff }, | ||
361 | { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff }, | ||
362 | { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff }, | ||
363 | { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff }, | ||
364 | { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff }, | ||
365 | { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff }, | ||
366 | { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff }, | ||
367 | { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff }, | ||
368 | { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff }, | ||
369 | { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff }, | ||
370 | { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff }, | ||
371 | { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff }, | ||
372 | { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff }, | ||
373 | { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff }, | ||
374 | { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff }, | ||
375 | { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff }, | ||
376 | { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff }, | ||
377 | { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff }, | ||
378 | { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },*/ | ||
379 | { AR5K_PHY_CCKTXCTL, 0x00000000 }, | ||
380 | { AR5K_PHY(642), 0x503e4646 }, | ||
381 | { AR5K_PHY_GAIN_2GHZ, 0x6480416c }, | ||
382 | { AR5K_PHY(644), 0x0199a003 }, | ||
383 | { AR5K_PHY(645), 0x044cd610 }, | ||
384 | { AR5K_PHY(646), 0x13800040 }, | ||
385 | { AR5K_PHY(647), 0x1be00060 }, | ||
386 | { AR5K_PHY(648), 0x0c53800a }, | ||
387 | { AR5K_PHY(649), 0x0014df3b }, | ||
388 | { AR5K_PHY(650), 0x000001b5 }, | ||
389 | { AR5K_PHY(651), 0x00000020 }, | ||
390 | }; | ||
391 | |||
392 | /* Initial mode-specific settings for AR5211 | ||
393 | * XXX: how about g / gTurbo ? RF5111 supports it, how about AR5211 ? | ||
394 | * Maybe 5211 supports OFDM-only g but we need to test it ! | ||
395 | */ | ||
396 | static const struct ath5k_ini_mode ar5211_ini_mode[] = { | ||
397 | { AR5K_TXCFG, | ||
398 | /* a aTurbo b */ | ||
399 | { 0x00000015, 0x00000015, 0x0000001d } }, | ||
400 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), | ||
401 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
402 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), | ||
403 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
404 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), | ||
405 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
406 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), | ||
407 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
408 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), | ||
409 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
410 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), | ||
411 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
412 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), | ||
413 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
414 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), | ||
415 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
416 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), | ||
417 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
418 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), | ||
419 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } }, | ||
420 | { AR5K_DCU_GBL_IFS_SLOT, | ||
421 | { 0x00000168, 0x000001e0, 0x000001b8 } }, | ||
422 | { AR5K_DCU_GBL_IFS_SIFS, | ||
423 | { 0x00000230, 0x000001e0, 0x000000b0 } }, | ||
424 | { AR5K_DCU_GBL_IFS_EIFS, | ||
425 | { 0x00000d98, 0x00001180, 0x00001f48 } }, | ||
426 | { AR5K_DCU_GBL_IFS_MISC, | ||
427 | { 0x0000a0e0, 0x00014068, 0x00005880 } }, | ||
428 | { AR5K_TIME_OUT, | ||
429 | { 0x04000400, 0x08000800, 0x20003000 } }, | ||
430 | { AR5K_USEC_5211, | ||
431 | { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95 } }, | ||
432 | { AR5K_PHY_TURBO, | ||
433 | { 0x00000000, 0x00000003, 0x00000000 } }, | ||
434 | { AR5K_PHY(8), | ||
435 | { 0x02020200, 0x02020200, 0x02010200 } }, | ||
436 | { AR5K_PHY(9), | ||
437 | { 0x00000e0e, 0x00000e0e, 0x00000707 } }, | ||
438 | { AR5K_PHY(10), | ||
439 | { 0x0a020001, 0x0a020001, 0x05010000 } }, | ||
440 | { AR5K_PHY(13), | ||
441 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | ||
442 | { AR5K_PHY(14), | ||
443 | { 0x00000007, 0x00000007, 0x0000000b } }, | ||
444 | { AR5K_PHY(17), | ||
445 | { 0x1372169c, 0x137216a5, 0x137216a8 } }, | ||
446 | { AR5K_PHY(18), | ||
447 | { 0x0018ba67, 0x0018ba67, 0x0018ba69 } }, | ||
448 | { AR5K_PHY(20), | ||
449 | { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, | ||
450 | { AR5K_PHY_SIG, | ||
451 | { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e } }, | ||
452 | { AR5K_PHY_AGCCOARSE, | ||
453 | { 0x31375d5e, 0x31375d5e, 0x313a5d5e } }, | ||
454 | { AR5K_PHY_AGCCTL, | ||
455 | { 0x0000bd10, 0x0000bd10, 0x0000bd38 } }, | ||
456 | { AR5K_PHY_NF, | ||
457 | { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, | ||
458 | { AR5K_PHY_RX_DELAY, | ||
459 | { 0x00002710, 0x00002710, 0x0000157c } }, | ||
460 | { AR5K_PHY(70), | ||
461 | { 0x00000190, 0x00000190, 0x00000084 } }, | ||
462 | { AR5K_PHY_FRAME_CTL_5211, | ||
463 | { 0x6fe01020, 0x6fe01020, 0x6fe00920 } }, | ||
464 | { AR5K_PHY_PCDAC_TXPOWER_BASE_5211, | ||
465 | { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff } }, | ||
466 | { AR5K_RF_BUFFER_CONTROL_4, | ||
467 | { 0x00000010, 0x00000014, 0x00000010 } }, | ||
468 | }; | ||
469 | |||
470 | /* Initial register settings for AR5212 */ | ||
471 | static const struct ath5k_ini ar5212_ini[] = { | ||
472 | { AR5K_RXDP, 0x00000000 }, | ||
473 | { AR5K_RXCFG, 0x00000005 }, | ||
474 | { AR5K_MIBC, 0x00000000 }, | ||
475 | { AR5K_TOPS, 0x00000008 }, | ||
476 | { AR5K_RXNOFRM, 0x00000008 }, | ||
477 | { AR5K_TXNOFRM, 0x00000010 }, | ||
478 | { AR5K_RPGTO, 0x00000000 }, | ||
479 | { AR5K_RFCNT, 0x0000001f }, | ||
480 | { AR5K_QUEUE_TXDP(0), 0x00000000 }, | ||
481 | { AR5K_QUEUE_TXDP(1), 0x00000000 }, | ||
482 | { AR5K_QUEUE_TXDP(2), 0x00000000 }, | ||
483 | { AR5K_QUEUE_TXDP(3), 0x00000000 }, | ||
484 | { AR5K_QUEUE_TXDP(4), 0x00000000 }, | ||
485 | { AR5K_QUEUE_TXDP(5), 0x00000000 }, | ||
486 | { AR5K_QUEUE_TXDP(6), 0x00000000 }, | ||
487 | { AR5K_QUEUE_TXDP(7), 0x00000000 }, | ||
488 | { AR5K_QUEUE_TXDP(8), 0x00000000 }, | ||
489 | { AR5K_QUEUE_TXDP(9), 0x00000000 }, | ||
490 | { AR5K_DCU_FP, 0x00000000 }, | ||
491 | { AR5K_DCU_TXP, 0x00000000 }, | ||
492 | { AR5K_DCU_TX_FILTER, 0x00000000 }, | ||
493 | /* Unknown table */ | ||
494 | { 0x1078, 0x00000000 }, | ||
495 | { 0x10b8, 0x00000000 }, | ||
496 | { 0x10f8, 0x00000000 }, | ||
497 | { 0x1138, 0x00000000 }, | ||
498 | { 0x1178, 0x00000000 }, | ||
499 | { 0x11b8, 0x00000000 }, | ||
500 | { 0x11f8, 0x00000000 }, | ||
501 | { 0x1238, 0x00000000 }, | ||
502 | { 0x1278, 0x00000000 }, | ||
503 | { 0x12b8, 0x00000000 }, | ||
504 | { 0x12f8, 0x00000000 }, | ||
505 | { 0x1338, 0x00000000 }, | ||
506 | { 0x1378, 0x00000000 }, | ||
507 | { 0x13b8, 0x00000000 }, | ||
508 | { 0x13f8, 0x00000000 }, | ||
509 | { 0x1438, 0x00000000 }, | ||
510 | { 0x1478, 0x00000000 }, | ||
511 | { 0x14b8, 0x00000000 }, | ||
512 | { 0x14f8, 0x00000000 }, | ||
513 | { 0x1538, 0x00000000 }, | ||
514 | { 0x1578, 0x00000000 }, | ||
515 | { 0x15b8, 0x00000000 }, | ||
516 | { 0x15f8, 0x00000000 }, | ||
517 | { 0x1638, 0x00000000 }, | ||
518 | { 0x1678, 0x00000000 }, | ||
519 | { 0x16b8, 0x00000000 }, | ||
520 | { 0x16f8, 0x00000000 }, | ||
521 | { 0x1738, 0x00000000 }, | ||
522 | { 0x1778, 0x00000000 }, | ||
523 | { 0x17b8, 0x00000000 }, | ||
524 | { 0x17f8, 0x00000000 }, | ||
525 | { 0x103c, 0x00000000 }, | ||
526 | { 0x107c, 0x00000000 }, | ||
527 | { 0x10bc, 0x00000000 }, | ||
528 | { 0x10fc, 0x00000000 }, | ||
529 | { 0x113c, 0x00000000 }, | ||
530 | { 0x117c, 0x00000000 }, | ||
531 | { 0x11bc, 0x00000000 }, | ||
532 | { 0x11fc, 0x00000000 }, | ||
533 | { 0x123c, 0x00000000 }, | ||
534 | { 0x127c, 0x00000000 }, | ||
535 | { 0x12bc, 0x00000000 }, | ||
536 | { 0x12fc, 0x00000000 }, | ||
537 | { 0x133c, 0x00000000 }, | ||
538 | { 0x137c, 0x00000000 }, | ||
539 | { 0x13bc, 0x00000000 }, | ||
540 | { 0x13fc, 0x00000000 }, | ||
541 | { 0x143c, 0x00000000 }, | ||
542 | { 0x147c, 0x00000000 }, | ||
543 | { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, | ||
544 | { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, | ||
545 | { AR5K_STA_ID1, 0x00000000 }, | ||
546 | { AR5K_BSS_ID0, 0x00000000 }, | ||
547 | { AR5K_BSS_ID1, 0x00000000 }, | ||
548 | /*{ AR5K_RSSI_THR, 0x00000000 },*/ /* Found on SuperAG cards */ | ||
549 | { AR5K_BEACON_5211, 0x00000000 }, /* Found on SuperAG cards */ | ||
550 | { AR5K_CFP_PERIOD_5211, 0x00000000 }, /* Found on SuperAG cards */ | ||
551 | { AR5K_TIMER0_5211, 0x00000030 }, /* Found on SuperAG cards */ | ||
552 | { AR5K_TIMER1_5211, 0x0007ffff }, /* Found on SuperAG cards */ | ||
553 | { AR5K_TIMER2_5211, 0x01ffffff }, /* Found on SuperAG cards */ | ||
554 | { AR5K_TIMER3_5211, 0x00000031 }, /* Found on SuperAG cards */ | ||
555 | { AR5K_CFP_DUR_5211, 0x00000000 }, /* Found on SuperAG cards */ | ||
556 | { AR5K_RX_FILTER_5211, 0x00000000 }, | ||
557 | { AR5K_DIAG_SW_5211, 0x00000000 }, | ||
558 | { AR5K_ADDAC_TEST, 0x00000000 }, | ||
559 | { AR5K_DEFAULT_ANTENNA, 0x00000000 }, | ||
560 | { 0x8080, 0x00000000 }, | ||
561 | /*{ 0x805c, 0xffffc7ff },*/ /* Old value */ | ||
562 | { 0x805c, 0x000fc78f }, | ||
563 | { AR5K_NAV_5211, 0x00000000 }, /* Not found on recent */ | ||
564 | { AR5K_RTS_OK_5211, 0x00000000 }, /* dumps but it makes */ | ||
565 | { AR5K_RTS_FAIL_5211, 0x00000000 }, /* sense to reset counters */ | ||
566 | { AR5K_ACK_FAIL_5211, 0x00000000 }, /* since pcu registers */ | ||
567 | { AR5K_FCS_FAIL_5211, 0x00000000 }, /* are skiped during chan*/ | ||
568 | { AR5K_BEACON_CNT_5211, 0x00000000 }, /* change */ | ||
569 | { AR5K_XRMODE, 0x2a82301a }, | ||
570 | { AR5K_XRDELAY, 0x05dc01e0 }, | ||
571 | { AR5K_XRTIMEOUT, 0x1f402710 }, | ||
572 | { AR5K_XRCHIRP, 0x01f40000 }, | ||
573 | { AR5K_XRSTOMP, 0x00001e1c }, | ||
574 | { AR5K_SLEEP0, 0x0002aaaa }, /* Found on SuperAG cards */ | ||
575 | { AR5K_SLEEP1, 0x02005555 }, /* Found on SuperAG cards */ | ||
576 | { AR5K_SLEEP2, 0x00000000 }, /* Found on SuperAG cards */ | ||
577 | { AR5K_BSS_IDM0, 0xffffffff }, | ||
578 | { AR5K_BSS_IDM1, 0x0000ffff }, | ||
579 | { AR5K_TXPC, 0x00000000 }, | ||
580 | { AR5K_PROFCNT_TX, 0x00000000 }, | ||
581 | { AR5K_PROFCNT_RX, 0x00000000 }, | ||
582 | { AR5K_PROFCNT_RXCLR, 0x00000000 }, | ||
583 | { AR5K_PROFCNT_CYCLE, 0x00000000 }, | ||
584 | { 0x80fc, 0x00000088 }, | ||
585 | { AR5K_RATE_DUR(0), 0x00000000 }, | ||
586 | { AR5K_RATE_DUR(1), 0x0000008c }, | ||
587 | { AR5K_RATE_DUR(2), 0x000000e4 }, | ||
588 | { AR5K_RATE_DUR(3), 0x000002d5 }, | ||
589 | { AR5K_RATE_DUR(4), 0x00000000 }, | ||
590 | { AR5K_RATE_DUR(5), 0x00000000 }, | ||
591 | { AR5K_RATE_DUR(6), 0x000000a0 }, | ||
592 | { AR5K_RATE_DUR(7), 0x000001c9 }, | ||
593 | { AR5K_RATE_DUR(8), 0x0000002c }, | ||
594 | { AR5K_RATE_DUR(9), 0x0000002c }, | ||
595 | { AR5K_RATE_DUR(10), 0x00000030 }, | ||
596 | { AR5K_RATE_DUR(11), 0x0000003c }, | ||
597 | { AR5K_RATE_DUR(12), 0x0000002c }, | ||
598 | { AR5K_RATE_DUR(13), 0x0000002c }, | ||
599 | { AR5K_RATE_DUR(14), 0x00000030 }, | ||
600 | { AR5K_RATE_DUR(15), 0x0000003c }, | ||
601 | { AR5K_RATE_DUR(16), 0x00000000 }, | ||
602 | { AR5K_RATE_DUR(17), 0x00000000 }, | ||
603 | { AR5K_RATE_DUR(18), 0x00000000 }, | ||
604 | { AR5K_RATE_DUR(19), 0x00000000 }, | ||
605 | { AR5K_RATE_DUR(20), 0x00000000 }, | ||
606 | { AR5K_RATE_DUR(21), 0x00000000 }, | ||
607 | { AR5K_RATE_DUR(22), 0x00000000 }, | ||
608 | { AR5K_RATE_DUR(23), 0x00000000 }, | ||
609 | { AR5K_RATE_DUR(24), 0x000000d5 }, | ||
610 | { AR5K_RATE_DUR(25), 0x000000df }, | ||
611 | { AR5K_RATE_DUR(26), 0x00000102 }, | ||
612 | { AR5K_RATE_DUR(27), 0x0000013a }, | ||
613 | { AR5K_RATE_DUR(28), 0x00000075 }, | ||
614 | { AR5K_RATE_DUR(29), 0x0000007f }, | ||
615 | { AR5K_RATE_DUR(30), 0x000000a2 }, | ||
616 | { AR5K_RATE_DUR(31), 0x00000000 }, | ||
617 | { 0x8100, 0x00010002}, | ||
618 | { AR5K_TSF_PARM, 0x00000001 }, | ||
619 | { 0x8108, 0x000000c0 }, | ||
620 | { AR5K_PHY_ERR_FIL, 0x00000000 }, | ||
621 | { 0x8110, 0x00000168 }, | ||
622 | { 0x8114, 0x00000000 }, | ||
623 | /* Some kind of table | ||
624 | * also notice ...03<-02<-01<-00) */ | ||
625 | { 0x87c0, 0x03020100 }, | ||
626 | { 0x87c4, 0x07060504 }, | ||
627 | { 0x87c8, 0x0b0a0908 }, | ||
628 | { 0x87cc, 0x0f0e0d0c }, | ||
629 | { 0x87d0, 0x13121110 }, | ||
630 | { 0x87d4, 0x17161514 }, | ||
631 | { 0x87d8, 0x1b1a1918 }, | ||
632 | { 0x87dc, 0x1f1e1d1c }, | ||
633 | /* loop ? */ | ||
634 | { 0x87e0, 0x03020100 }, | ||
635 | { 0x87e4, 0x07060504 }, | ||
636 | { 0x87e8, 0x0b0a0908 }, | ||
637 | { 0x87ec, 0x0f0e0d0c }, | ||
638 | { 0x87f0, 0x13121110 }, | ||
639 | { 0x87f4, 0x17161514 }, | ||
640 | { 0x87f8, 0x1b1a1918 }, | ||
641 | { 0x87fc, 0x1f1e1d1c }, | ||
642 | /* PHY registers */ | ||
643 | /*{ AR5K_PHY_AGC, 0x00000000 },*/ | ||
644 | { AR5K_PHY(3), 0xad848e19 }, | ||
645 | { AR5K_PHY(4), 0x7d28e000 }, | ||
646 | { AR5K_PHY_TIMING_3, 0x9c0a9f6b }, | ||
647 | { AR5K_PHY_ACT, 0x00000000 }, | ||
648 | /*{ AR5K_PHY(11), 0x00022ffe },*/ | ||
649 | /*{ AR5K_PHY(15), 0x00020100 },*/ | ||
650 | { AR5K_PHY(16), 0x206a017a }, | ||
651 | /*{ AR5K_PHY(19), 0x1284613c },*/ | ||
652 | { AR5K_PHY(21), 0x00000859 }, | ||
653 | { AR5K_PHY(64), 0x00000000 }, | ||
654 | { AR5K_PHY(65), 0x00000000 }, | ||
655 | { AR5K_PHY(66), 0x00000000 }, | ||
656 | { AR5K_PHY(67), 0x00800000 }, | ||
657 | { AR5K_PHY(68), 0x00000001 }, | ||
658 | /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */ | ||
659 | { AR5K_PHY(71), 0x00000c80 }, | ||
660 | { AR5K_PHY_IQ, 0x05100000 }, | ||
661 | { AR5K_PHY(74), 0x00000001 }, | ||
662 | { AR5K_PHY(75), 0x00000004 }, | ||
663 | { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 }, | ||
664 | { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d }, | ||
665 | { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f }, | ||
666 | /*{ AR5K_PHY(80), 0x00000004 },*/ | ||
667 | { AR5K_PHY(82), 0x9280b212 }, | ||
668 | { AR5K_PHY_RADAR, 0x5d50e188 }, | ||
669 | /*{ AR5K_PHY(86), 0x000000ff },*/ | ||
670 | { AR5K_PHY(87), 0x004b6a8e }, | ||
671 | { AR5K_PHY(90), 0x000003ce }, | ||
672 | { AR5K_PHY(92), 0x192fb515 }, | ||
673 | /*{ AR5K_PHY(93), 0x00000000 },*/ | ||
674 | { AR5K_PHY(94), 0x00000001 }, | ||
675 | { AR5K_PHY(95), 0x00000000 }, | ||
676 | /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */ | ||
677 | /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */ | ||
678 | { AR5K_PHY(644), 0x00806333 }, | ||
679 | { AR5K_PHY(645), 0x00106c10 }, | ||
680 | { AR5K_PHY(646), 0x009c4060 }, | ||
681 | /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */ | ||
682 | { AR5K_PHY(647), 0x1483800a }, | ||
683 | { AR5K_PHY(648), 0x01831061 }, | ||
684 | { AR5K_PHY(649), 0x00000400 }, | ||
685 | /*{ AR5K_PHY(650), 0x000001b5 },*/ | ||
686 | { AR5K_PHY(651), 0x00000000 }, | ||
687 | { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, | ||
688 | { AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, | ||
689 | /*{ AR5K_PHY(655), 0x13c889af },*/ | ||
690 | { AR5K_PHY(656), 0x38490a20 }, | ||
691 | { AR5K_PHY(657), 0x00007bb6 }, | ||
692 | { AR5K_PHY(658), 0x0fff3ffc }, | ||
693 | /*{ AR5K_PHY_CCKTXCTL, 0x00000000 },*/ | ||
694 | }; | ||
695 | |||
696 | /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ | ||
697 | static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { | ||
698 | { AR5K_PHY(640), | ||
699 | /* a/XR aTurbo b g (DYN) gTurbo */ | ||
700 | { 0x00000008, 0x00000008, 0x0000000b, 0x0000000e, 0x0000000e } }, | ||
701 | { AR5K_PHY(0), | ||
702 | { 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 } }, | ||
703 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), | ||
704 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
705 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), | ||
706 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
707 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), | ||
708 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
709 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), | ||
710 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
711 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), | ||
712 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
713 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), | ||
714 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
715 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), | ||
716 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
717 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), | ||
718 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
719 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), | ||
720 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
721 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), | ||
722 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | ||
723 | { AR5K_DCU_GBL_IFS_SIFS, | ||
724 | { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, | ||
725 | { AR5K_DCU_GBL_IFS_SLOT, | ||
726 | { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, | ||
727 | { AR5K_DCU_GBL_IFS_EIFS, | ||
728 | { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, | ||
729 | { AR5K_DCU_GBL_IFS_MISC, | ||
730 | { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, | ||
731 | { AR5K_TIME_OUT, | ||
732 | { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, | ||
733 | { AR5K_PHY_TURBO, | ||
734 | { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, | ||
735 | { AR5K_PHY(8), | ||
736 | { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, | ||
737 | { AR5K_PHY(9), | ||
738 | { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, | ||
739 | { AR5K_PHY(17), | ||
740 | { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, | ||
741 | { AR5K_PHY_AGCCTL, | ||
742 | { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, | ||
743 | { AR5K_PHY_NF, | ||
744 | { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, | ||
745 | { AR5K_PHY(26), | ||
746 | { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, | ||
747 | { AR5K_PHY(70), | ||
748 | { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, | ||
749 | { AR5K_PHY(73), | ||
750 | { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, | ||
751 | { 0xa230, | ||
752 | { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, | ||
753 | }; | ||
754 | |||
755 | /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ | ||
756 | /* New dump pending */ | ||
757 | static const struct ath5k_ini_mode ar5212_rf5111_ini_mode_end[] = { | ||
758 | { AR5K_PHY(640), /* This one differs from ar5212_ini_mode_start ! */ | ||
759 | /* a/XR aTurbo b g (DYN) gTurbo */ | ||
760 | { 0x00000000, 0x00000000, 0x00000003, 0x00000006, 0x00000006 } }, | ||
761 | { AR5K_TXCFG, | ||
762 | { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, | ||
763 | { AR5K_USEC_5211, | ||
764 | { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, | ||
765 | { AR5K_PHY(10), | ||
766 | { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, | ||
767 | { AR5K_PHY(13), | ||
768 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | ||
769 | { AR5K_PHY(14), | ||
770 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | ||
771 | { AR5K_PHY(18), | ||
772 | { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, | ||
773 | { AR5K_PHY(20), | ||
774 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, | ||
775 | { AR5K_PHY_SIG, | ||
776 | { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, | ||
777 | { AR5K_PHY_AGCCOARSE, | ||
778 | { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, | ||
779 | { AR5K_PHY(27), | ||
780 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, | ||
781 | { AR5K_PHY_RX_DELAY, | ||
782 | { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, | ||
783 | { AR5K_PHY_FRAME_CTL_5211, | ||
784 | { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, | ||
785 | { AR5K_PHY_GAIN_2GHZ, | ||
786 | { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, | ||
787 | { 0xa21c, | ||
788 | { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, | ||
789 | { AR5K_DCU_FP, | ||
790 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
791 | { AR5K_PHY_AGC, | ||
792 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
793 | { AR5K_PHY(11), | ||
794 | { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } }, | ||
795 | { AR5K_PHY(15), | ||
796 | { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } }, | ||
797 | { AR5K_PHY(19), | ||
798 | { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } }, | ||
799 | { AR5K_PHY_PAPD_PROBE, | ||
800 | { 0x00004883, 0x00004883, 0x00004883, 0x00004883, 0x00004883 } }, | ||
801 | { AR5K_PHY(80), | ||
802 | { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } }, | ||
803 | { AR5K_PHY(86), | ||
804 | { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } }, | ||
805 | { AR5K_PHY(93), | ||
806 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
807 | { AR5K_PHY_SPENDING, | ||
808 | { 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018 } }, | ||
809 | { AR5K_PHY_CCKTXCTL, | ||
810 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
811 | { AR5K_PHY(642), | ||
812 | { 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | ||
813 | { 0xa23c, | ||
814 | { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } }, | ||
815 | }; | ||
816 | |||
817 | /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ | ||
818 | /* XXX: No dumps for turbog yet, but i found settings from old values so it should be ok */ | ||
819 | static const struct ath5k_ini_mode ar5212_rf5112_ini_mode_end[] = { | ||
820 | { AR5K_TXCFG, | ||
821 | /* a/XR aTurbo b g (DYN) gTurbo */ | ||
822 | { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, | ||
823 | { AR5K_USEC_5211, | ||
824 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | ||
825 | { AR5K_PHY(10), | ||
826 | { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, | ||
827 | { AR5K_PHY(13), | ||
828 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | ||
829 | { AR5K_PHY(14), | ||
830 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | ||
831 | { AR5K_PHY(18), | ||
832 | { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, | ||
833 | { AR5K_PHY(20), | ||
834 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, | ||
835 | { AR5K_PHY_SIG, | ||
836 | { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, | ||
837 | { AR5K_PHY_AGCCOARSE, | ||
838 | { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, | ||
839 | { AR5K_PHY(27), | ||
840 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | ||
841 | { AR5K_PHY_RX_DELAY, | ||
842 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | ||
843 | { AR5K_PHY_FRAME_CTL_5211, | ||
844 | { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, | ||
845 | { AR5K_PHY_CCKTXCTL, | ||
846 | { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, | ||
847 | { AR5K_PHY(642), | ||
848 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | ||
849 | { AR5K_PHY_GAIN_2GHZ, | ||
850 | { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, | ||
851 | { 0xa21c, | ||
852 | { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, | ||
853 | { AR5K_DCU_FP, | ||
854 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
855 | { AR5K_PHY_AGC, | ||
856 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
857 | { AR5K_PHY(11), | ||
858 | { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } }, | ||
859 | { AR5K_PHY(15), | ||
860 | { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } }, | ||
861 | { AR5K_PHY(19), | ||
862 | { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } }, | ||
863 | { AR5K_PHY_PAPD_PROBE, | ||
864 | { 0x00004882, 0x00004882, 0x00004882, 0x00004882, 0x00004882 } }, | ||
865 | { AR5K_PHY(80), | ||
866 | { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } }, | ||
867 | { AR5K_PHY(86), | ||
868 | { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } }, | ||
869 | { AR5K_PHY(93), | ||
870 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
871 | { 0xa228, | ||
872 | { 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5 } }, | ||
873 | { 0xa23c, | ||
874 | { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } }, | ||
875 | }; | ||
876 | |||
877 | /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ | ||
878 | /* XXX: No dumps for turbog yet, so turbog is the same with g here with some | ||
879 | * minor tweaking based on dumps from other chips */ | ||
880 | static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { | ||
881 | { AR5K_TXCFG, | ||
882 | /* a/XR aTurbo b g gTurbo */ | ||
883 | { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, | ||
884 | { AR5K_USEC_5211, | ||
885 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | ||
886 | { AR5K_PHY(10), | ||
887 | { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, | ||
888 | { AR5K_PHY(13), | ||
889 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | ||
890 | { AR5K_PHY(14), | ||
891 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | ||
892 | { AR5K_PHY(18), | ||
893 | { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, | ||
894 | { AR5K_PHY(20), | ||
895 | { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, | ||
896 | { AR5K_PHY_SIG, | ||
897 | { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, | ||
898 | { AR5K_PHY_AGCCOARSE, | ||
899 | { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, | ||
900 | { AR5K_PHY(27), | ||
901 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | ||
902 | { AR5K_PHY_RX_DELAY, | ||
903 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | ||
904 | { AR5K_PHY_FRAME_CTL_5211, | ||
905 | { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, | ||
906 | { AR5K_PHY_CCKTXCTL, | ||
907 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
908 | { AR5K_PHY(642), | ||
909 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | ||
910 | { AR5K_PHY_GAIN_2GHZ, | ||
911 | { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, | ||
912 | { 0xa21c, | ||
913 | { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, | ||
914 | { 0xa300, | ||
915 | { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, | ||
916 | { 0xa304, | ||
917 | { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, | ||
918 | { 0xa308, | ||
919 | { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, | ||
920 | { 0xa30c, | ||
921 | { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, | ||
922 | { 0xa310, | ||
923 | { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, | ||
924 | { 0xa314, | ||
925 | { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, | ||
926 | { 0xa318, | ||
927 | { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, | ||
928 | { 0xa31c, | ||
929 | { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, | ||
930 | { 0xa320, | ||
931 | { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, | ||
932 | { 0xa324, | ||
933 | { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, | ||
934 | { 0xa328, | ||
935 | { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, | ||
936 | { 0xa32c, | ||
937 | { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, | ||
938 | { 0xa330, | ||
939 | { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, | ||
940 | { 0xa334, | ||
941 | { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, | ||
942 | { AR5K_DCU_FP, | ||
943 | { 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0 } }, | ||
944 | { 0x4068, | ||
945 | { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, | ||
946 | { 0x8060, | ||
947 | { 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f } }, | ||
948 | { 0x809c, | ||
949 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
950 | { 0x80a0, | ||
951 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
952 | { 0x8118, | ||
953 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
954 | { 0x811c, | ||
955 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
956 | { 0x8120, | ||
957 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
958 | { 0x8124, | ||
959 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
960 | { 0x8128, | ||
961 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
962 | { 0x812c, | ||
963 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
964 | { 0x8130, | ||
965 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
966 | { 0x8134, | ||
967 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
968 | { 0x8138, | ||
969 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
970 | { 0x813c, | ||
971 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
972 | { 0x8140, | ||
973 | { 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9 } }, | ||
974 | { 0x8144, | ||
975 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
976 | { AR5K_PHY_AGC, | ||
977 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
978 | { AR5K_PHY(11), | ||
979 | { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } }, | ||
980 | { AR5K_PHY(15), | ||
981 | { 0x00200400, 0x00200400, 0x00200400, 0x00200400, 0x00200400 } }, | ||
982 | { AR5K_PHY(19), | ||
983 | { 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c } }, | ||
984 | { AR5K_PHY_SCR, | ||
985 | { 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f } }, | ||
986 | { AR5K_PHY_SLMT, | ||
987 | { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, | ||
988 | { AR5K_PHY_SCAL, | ||
989 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
990 | { AR5K_PHY(86), | ||
991 | { 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff } }, | ||
992 | { AR5K_PHY(96), | ||
993 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
994 | { AR5K_PHY(97), | ||
995 | { 0x02800000, 0x02800000, 0x02800000, 0x02800000, 0x02800000 } }, | ||
996 | { AR5K_PHY(104), | ||
997 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
998 | { AR5K_PHY(120), | ||
999 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1000 | { AR5K_PHY(121), | ||
1001 | { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } }, | ||
1002 | { AR5K_PHY(122), | ||
1003 | { 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478 } }, | ||
1004 | { AR5K_PHY(123), | ||
1005 | { 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa } }, | ||
1006 | { AR5K_PHY_SCLOCK, | ||
1007 | { 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c } }, | ||
1008 | { AR5K_PHY_SDELAY, | ||
1009 | { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } }, | ||
1010 | { AR5K_PHY_SPENDING, | ||
1011 | { 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000014 } }, | ||
1012 | { 0xa228, | ||
1013 | { 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5 } }, | ||
1014 | { 0xa23c, | ||
1015 | { 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af } }, | ||
1016 | { 0xa24c, | ||
1017 | { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, | ||
1018 | { 0xa250, | ||
1019 | { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } }, | ||
1020 | { 0xa254, | ||
1021 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1022 | { 0xa258, | ||
1023 | { 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380 } }, | ||
1024 | { 0xa25c, | ||
1025 | { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } }, | ||
1026 | { 0xa260, | ||
1027 | { 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01 } }, | ||
1028 | { 0xa264, | ||
1029 | { 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11 } }, | ||
1030 | { 0xa268, | ||
1031 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1032 | { 0xa26c, | ||
1033 | { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } }, | ||
1034 | { 0xa270, | ||
1035 | { 0x00820820, 0x00820820, 0x00820820, 0x00820820, 0x00820820 } }, | ||
1036 | { 0xa274, | ||
1037 | { 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa } }, | ||
1038 | { 0xa278, | ||
1039 | { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } }, | ||
1040 | { 0xa27c, | ||
1041 | { 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce } }, | ||
1042 | { 0xa338, | ||
1043 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1044 | { 0xa33c, | ||
1045 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1046 | { 0xa340, | ||
1047 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1048 | { 0xa344, | ||
1049 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1050 | { 0xa348, | ||
1051 | { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1052 | { 0xa34c, | ||
1053 | { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1054 | { 0xa350, | ||
1055 | { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } }, | ||
1056 | { 0xa354, | ||
1057 | { 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff } }, | ||
1058 | { 0xa358, | ||
1059 | { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } }, | ||
1060 | { 0xa35c, | ||
1061 | { 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f } }, | ||
1062 | { 0xa360, | ||
1063 | { 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207 } }, | ||
1064 | { 0xa364, | ||
1065 | { 0x17601685, 0x17601685, 0x17601685, 0x17601685, 0x17601685 } }, | ||
1066 | { 0xa368, | ||
1067 | { 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104 } }, | ||
1068 | { 0xa36c, | ||
1069 | { 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03 } }, | ||
1070 | { 0xa370, | ||
1071 | { 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883 } }, | ||
1072 | { 0xa374, | ||
1073 | { 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803 } }, | ||
1074 | { 0xa378, | ||
1075 | { 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682 } }, | ||
1076 | { 0xa37c, | ||
1077 | { 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482 } }, | ||
1078 | { 0xa380, | ||
1079 | { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } }, | ||
1080 | { 0xa384, | ||
1081 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, | ||
1082 | }; | ||
1083 | |||
1084 | /* | ||
1085 | * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with | ||
1086 | * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) | ||
1087 | */ | ||
1088 | |||
1089 | /* RF5111 Initial BaseBand Gain settings */ | ||
1090 | static const struct ath5k_ini rf5111_ini_bbgain[] = { | ||
1091 | { AR5K_BB_GAIN(0), 0x00000000 }, | ||
1092 | { AR5K_BB_GAIN(1), 0x00000020 }, | ||
1093 | { AR5K_BB_GAIN(2), 0x00000010 }, | ||
1094 | { AR5K_BB_GAIN(3), 0x00000030 }, | ||
1095 | { AR5K_BB_GAIN(4), 0x00000008 }, | ||
1096 | { AR5K_BB_GAIN(5), 0x00000028 }, | ||
1097 | { AR5K_BB_GAIN(6), 0x00000004 }, | ||
1098 | { AR5K_BB_GAIN(7), 0x00000024 }, | ||
1099 | { AR5K_BB_GAIN(8), 0x00000014 }, | ||
1100 | { AR5K_BB_GAIN(9), 0x00000034 }, | ||
1101 | { AR5K_BB_GAIN(10), 0x0000000c }, | ||
1102 | { AR5K_BB_GAIN(11), 0x0000002c }, | ||
1103 | { AR5K_BB_GAIN(12), 0x00000002 }, | ||
1104 | { AR5K_BB_GAIN(13), 0x00000022 }, | ||
1105 | { AR5K_BB_GAIN(14), 0x00000012 }, | ||
1106 | { AR5K_BB_GAIN(15), 0x00000032 }, | ||
1107 | { AR5K_BB_GAIN(16), 0x0000000a }, | ||
1108 | { AR5K_BB_GAIN(17), 0x0000002a }, | ||
1109 | { AR5K_BB_GAIN(18), 0x00000006 }, | ||
1110 | { AR5K_BB_GAIN(19), 0x00000026 }, | ||
1111 | { AR5K_BB_GAIN(20), 0x00000016 }, | ||
1112 | { AR5K_BB_GAIN(21), 0x00000036 }, | ||
1113 | { AR5K_BB_GAIN(22), 0x0000000e }, | ||
1114 | { AR5K_BB_GAIN(23), 0x0000002e }, | ||
1115 | { AR5K_BB_GAIN(24), 0x00000001 }, | ||
1116 | { AR5K_BB_GAIN(25), 0x00000021 }, | ||
1117 | { AR5K_BB_GAIN(26), 0x00000011 }, | ||
1118 | { AR5K_BB_GAIN(27), 0x00000031 }, | ||
1119 | { AR5K_BB_GAIN(28), 0x00000009 }, | ||
1120 | { AR5K_BB_GAIN(29), 0x00000029 }, | ||
1121 | { AR5K_BB_GAIN(30), 0x00000005 }, | ||
1122 | { AR5K_BB_GAIN(31), 0x00000025 }, | ||
1123 | { AR5K_BB_GAIN(32), 0x00000015 }, | ||
1124 | { AR5K_BB_GAIN(33), 0x00000035 }, | ||
1125 | { AR5K_BB_GAIN(34), 0x0000000d }, | ||
1126 | { AR5K_BB_GAIN(35), 0x0000002d }, | ||
1127 | { AR5K_BB_GAIN(36), 0x00000003 }, | ||
1128 | { AR5K_BB_GAIN(37), 0x00000023 }, | ||
1129 | { AR5K_BB_GAIN(38), 0x00000013 }, | ||
1130 | { AR5K_BB_GAIN(39), 0x00000033 }, | ||
1131 | { AR5K_BB_GAIN(40), 0x0000000b }, | ||
1132 | { AR5K_BB_GAIN(41), 0x0000002b }, | ||
1133 | { AR5K_BB_GAIN(42), 0x0000002b }, | ||
1134 | { AR5K_BB_GAIN(43), 0x0000002b }, | ||
1135 | { AR5K_BB_GAIN(44), 0x0000002b }, | ||
1136 | { AR5K_BB_GAIN(45), 0x0000002b }, | ||
1137 | { AR5K_BB_GAIN(46), 0x0000002b }, | ||
1138 | { AR5K_BB_GAIN(47), 0x0000002b }, | ||
1139 | { AR5K_BB_GAIN(48), 0x0000002b }, | ||
1140 | { AR5K_BB_GAIN(49), 0x0000002b }, | ||
1141 | { AR5K_BB_GAIN(50), 0x0000002b }, | ||
1142 | { AR5K_BB_GAIN(51), 0x0000002b }, | ||
1143 | { AR5K_BB_GAIN(52), 0x0000002b }, | ||
1144 | { AR5K_BB_GAIN(53), 0x0000002b }, | ||
1145 | { AR5K_BB_GAIN(54), 0x0000002b }, | ||
1146 | { AR5K_BB_GAIN(55), 0x0000002b }, | ||
1147 | { AR5K_BB_GAIN(56), 0x0000002b }, | ||
1148 | { AR5K_BB_GAIN(57), 0x0000002b }, | ||
1149 | { AR5K_BB_GAIN(58), 0x0000002b }, | ||
1150 | { AR5K_BB_GAIN(59), 0x0000002b }, | ||
1151 | { AR5K_BB_GAIN(60), 0x0000002b }, | ||
1152 | { AR5K_BB_GAIN(61), 0x0000002b }, | ||
1153 | { AR5K_BB_GAIN(62), 0x00000002 }, | ||
1154 | { AR5K_BB_GAIN(63), 0x00000016 }, | ||
1155 | }; | ||
1156 | |||
1157 | /* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414) */ | ||
1158 | static const struct ath5k_ini rf5112_ini_bbgain[] = { | ||
1159 | { AR5K_BB_GAIN(0), 0x00000000 }, | ||
1160 | { AR5K_BB_GAIN(1), 0x00000001 }, | ||
1161 | { AR5K_BB_GAIN(2), 0x00000002 }, | ||
1162 | { AR5K_BB_GAIN(3), 0x00000003 }, | ||
1163 | { AR5K_BB_GAIN(4), 0x00000004 }, | ||
1164 | { AR5K_BB_GAIN(5), 0x00000005 }, | ||
1165 | { AR5K_BB_GAIN(6), 0x00000008 }, | ||
1166 | { AR5K_BB_GAIN(7), 0x00000009 }, | ||
1167 | { AR5K_BB_GAIN(8), 0x0000000a }, | ||
1168 | { AR5K_BB_GAIN(9), 0x0000000b }, | ||
1169 | { AR5K_BB_GAIN(10), 0x0000000c }, | ||
1170 | { AR5K_BB_GAIN(11), 0x0000000d }, | ||
1171 | { AR5K_BB_GAIN(12), 0x00000010 }, | ||
1172 | { AR5K_BB_GAIN(13), 0x00000011 }, | ||
1173 | { AR5K_BB_GAIN(14), 0x00000012 }, | ||
1174 | { AR5K_BB_GAIN(15), 0x00000013 }, | ||
1175 | { AR5K_BB_GAIN(16), 0x00000014 }, | ||
1176 | { AR5K_BB_GAIN(17), 0x00000015 }, | ||
1177 | { AR5K_BB_GAIN(18), 0x00000018 }, | ||
1178 | { AR5K_BB_GAIN(19), 0x00000019 }, | ||
1179 | { AR5K_BB_GAIN(20), 0x0000001a }, | ||
1180 | { AR5K_BB_GAIN(21), 0x0000001b }, | ||
1181 | { AR5K_BB_GAIN(22), 0x0000001c }, | ||
1182 | { AR5K_BB_GAIN(23), 0x0000001d }, | ||
1183 | { AR5K_BB_GAIN(24), 0x00000020 }, | ||
1184 | { AR5K_BB_GAIN(25), 0x00000021 }, | ||
1185 | { AR5K_BB_GAIN(26), 0x00000022 }, | ||
1186 | { AR5K_BB_GAIN(27), 0x00000023 }, | ||
1187 | { AR5K_BB_GAIN(28), 0x00000024 }, | ||
1188 | { AR5K_BB_GAIN(29), 0x00000025 }, | ||
1189 | { AR5K_BB_GAIN(30), 0x00000028 }, | ||
1190 | { AR5K_BB_GAIN(31), 0x00000029 }, | ||
1191 | { AR5K_BB_GAIN(32), 0x0000002a }, | ||
1192 | { AR5K_BB_GAIN(33), 0x0000002b }, | ||
1193 | { AR5K_BB_GAIN(34), 0x0000002c }, | ||
1194 | { AR5K_BB_GAIN(35), 0x0000002d }, | ||
1195 | { AR5K_BB_GAIN(36), 0x00000030 }, | ||
1196 | { AR5K_BB_GAIN(37), 0x00000031 }, | ||
1197 | { AR5K_BB_GAIN(38), 0x00000032 }, | ||
1198 | { AR5K_BB_GAIN(39), 0x00000033 }, | ||
1199 | { AR5K_BB_GAIN(40), 0x00000034 }, | ||
1200 | { AR5K_BB_GAIN(41), 0x00000035 }, | ||
1201 | { AR5K_BB_GAIN(42), 0x00000035 }, | ||
1202 | { AR5K_BB_GAIN(43), 0x00000035 }, | ||
1203 | { AR5K_BB_GAIN(44), 0x00000035 }, | ||
1204 | { AR5K_BB_GAIN(45), 0x00000035 }, | ||
1205 | { AR5K_BB_GAIN(46), 0x00000035 }, | ||
1206 | { AR5K_BB_GAIN(47), 0x00000035 }, | ||
1207 | { AR5K_BB_GAIN(48), 0x00000035 }, | ||
1208 | { AR5K_BB_GAIN(49), 0x00000035 }, | ||
1209 | { AR5K_BB_GAIN(50), 0x00000035 }, | ||
1210 | { AR5K_BB_GAIN(51), 0x00000035 }, | ||
1211 | { AR5K_BB_GAIN(52), 0x00000035 }, | ||
1212 | { AR5K_BB_GAIN(53), 0x00000035 }, | ||
1213 | { AR5K_BB_GAIN(54), 0x00000035 }, | ||
1214 | { AR5K_BB_GAIN(55), 0x00000035 }, | ||
1215 | { AR5K_BB_GAIN(56), 0x00000035 }, | ||
1216 | { AR5K_BB_GAIN(57), 0x00000035 }, | ||
1217 | { AR5K_BB_GAIN(58), 0x00000035 }, | ||
1218 | { AR5K_BB_GAIN(59), 0x00000035 }, | ||
1219 | { AR5K_BB_GAIN(60), 0x00000035 }, | ||
1220 | { AR5K_BB_GAIN(61), 0x00000035 }, | ||
1221 | { AR5K_BB_GAIN(62), 0x00000010 }, | ||
1222 | { AR5K_BB_GAIN(63), 0x0000001a }, | ||
1223 | }; | ||
1224 | |||
1225 | |||
1226 | /* | ||
1227 | * Write initial register dump | ||
1228 | */ | ||
1229 | static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, | ||
1230 | const struct ath5k_ini *ini_regs, bool change_channel) | ||
1231 | { | ||
1232 | unsigned int i; | ||
1233 | |||
1234 | /* Write initial registers */ | ||
1235 | for (i = 0; i < size; i++) { | ||
1236 | /* On channel change there is | ||
1237 | * no need to mess with PCU */ | ||
1238 | if (change_channel && | ||
1239 | ini_regs[i].ini_register >= AR5K_PCU_MIN && | ||
1240 | ini_regs[i].ini_register <= AR5K_PCU_MAX) | ||
1241 | continue; | ||
1242 | |||
1243 | switch (ini_regs[i].ini_mode) { | ||
1244 | case AR5K_INI_READ: | ||
1245 | /* Cleared on read */ | ||
1246 | ath5k_hw_reg_read(ah, ini_regs[i].ini_register); | ||
1247 | break; | ||
1248 | case AR5K_INI_WRITE: | ||
1249 | default: | ||
1250 | AR5K_REG_WAIT(i); | ||
1251 | ath5k_hw_reg_write(ah, ini_regs[i].ini_value, | ||
1252 | ini_regs[i].ini_register); | ||
1253 | } | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, | ||
1258 | unsigned int size, const struct ath5k_ini_mode *ini_mode, | ||
1259 | u8 mode) | ||
1260 | { | ||
1261 | unsigned int i; | ||
1262 | |||
1263 | for (i = 0; i < size; i++) { | ||
1264 | AR5K_REG_WAIT(i); | ||
1265 | ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode], | ||
1266 | (u32)ini_mode[i].mode_register); | ||
1267 | } | ||
1268 | |||
1269 | } | ||
1270 | |||
1271 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | ||
1272 | { | ||
1273 | /* | ||
1274 | * Write initial register settings | ||
1275 | */ | ||
1276 | |||
1277 | /* For AR5212 and combatible */ | ||
1278 | if (ah->ah_version == AR5K_AR5212){ | ||
1279 | |||
1280 | /* First set of mode-specific settings */ | ||
1281 | ath5k_hw_ini_mode_registers(ah, | ||
1282 | ARRAY_SIZE(ar5212_ini_mode_start), | ||
1283 | ar5212_ini_mode_start, mode); | ||
1284 | |||
1285 | /* | ||
1286 | * Write initial settings common for all modes | ||
1287 | */ | ||
1288 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini), | ||
1289 | ar5212_ini, change_channel); | ||
1290 | |||
1291 | /* Second set of mode-specific settings */ | ||
1292 | if (ah->ah_radio == AR5K_RF5111){ | ||
1293 | ath5k_hw_ini_mode_registers(ah, | ||
1294 | ARRAY_SIZE(ar5212_rf5111_ini_mode_end), | ||
1295 | ar5212_rf5111_ini_mode_end, mode); | ||
1296 | /* Baseband gain table */ | ||
1297 | ath5k_hw_ini_registers(ah, | ||
1298 | ARRAY_SIZE(rf5111_ini_bbgain), | ||
1299 | rf5111_ini_bbgain, change_channel); | ||
1300 | } else if (ah->ah_radio == AR5K_RF5112){ | ||
1301 | ath5k_hw_ini_mode_registers(ah, | ||
1302 | ARRAY_SIZE(ar5212_rf5112_ini_mode_end), | ||
1303 | ar5212_rf5112_ini_mode_end, mode); | ||
1304 | /* Baseband gain table */ | ||
1305 | ath5k_hw_ini_registers(ah, | ||
1306 | ARRAY_SIZE(rf5112_ini_bbgain), | ||
1307 | rf5112_ini_bbgain, change_channel); | ||
1308 | } else if (ah->ah_radio == AR5K_RF5413){ | ||
1309 | ath5k_hw_ini_mode_registers(ah, | ||
1310 | ARRAY_SIZE(rf5413_ini_mode_end), | ||
1311 | rf5413_ini_mode_end, mode); | ||
1312 | /* Baseband gain table */ | ||
1313 | ath5k_hw_ini_registers(ah, | ||
1314 | ARRAY_SIZE(rf5112_ini_bbgain), | ||
1315 | rf5112_ini_bbgain, change_channel); | ||
1316 | } | ||
1317 | /* For AR5211 */ | ||
1318 | } else if (ah->ah_version == AR5K_AR5211) { | ||
1319 | |||
1320 | if(mode > 2){ /* AR5K_INI_VAL_11B */ | ||
1321 | ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode); | ||
1322 | return -EINVAL; | ||
1323 | } | ||
1324 | |||
1325 | /* Mode-specific settings */ | ||
1326 | ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode), | ||
1327 | ar5211_ini_mode, mode); | ||
1328 | |||
1329 | /* | ||
1330 | * Write initial settings common for all modes | ||
1331 | */ | ||
1332 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), | ||
1333 | ar5211_ini, change_channel); | ||
1334 | |||
1335 | /* AR5211 only comes with 5111 */ | ||
1336 | |||
1337 | /* Baseband gain table */ | ||
1338 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), | ||
1339 | rf5111_ini_bbgain, change_channel); | ||
1340 | /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ | ||
1341 | } else if (ah->ah_version == AR5K_AR5210) { | ||
1342 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), | ||
1343 | ar5210_ini, change_channel); | ||
1344 | } | ||
1345 | |||
1346 | return 0; | ||
1347 | } | ||
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c new file mode 100644 index 000000000000..b95941797141 --- /dev/null +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -0,0 +1,2071 @@ | |||
1 | /* | ||
2 | * PHY functions | ||
3 | * | ||
4 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | ||
5 | * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com> | ||
6 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #include "ath5k.h" | ||
25 | #include "reg.h" | ||
26 | #include "base.h" | ||
27 | |||
28 | /* Struct to hold initial RF register values (RF Banks) */ | ||
29 | struct ath5k_ini_rf { | ||
30 | u8 rf_bank; /* check out ath5k_reg.h */ | ||
31 | u16 rf_register; /* register address */ | ||
32 | u32 rf_value[5]; /* register value for different modes (above) */ | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * Mode-specific RF Gain table (64bytes) for RF5111/5112 | ||
37 | * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial | ||
38 | * RF Gain values are included in AR5K_AR5210_INI) | ||
39 | */ | ||
40 | struct ath5k_ini_rfgain { | ||
41 | u16 rfg_register; /* RF Gain register address */ | ||
42 | u32 rfg_value[2]; /* [freq (see below)] */ | ||
43 | }; | ||
44 | |||
45 | struct ath5k_gain_opt { | ||
46 | u32 go_default; | ||
47 | u32 go_steps_count; | ||
48 | const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; | ||
49 | }; | ||
50 | |||
51 | /* RF5111 mode-specific init registers */ | ||
52 | static const struct ath5k_ini_rf rfregs_5111[] = { | ||
53 | { 0, 0x989c, | ||
54 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | ||
55 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
56 | { 0, 0x989c, | ||
57 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
58 | { 0, 0x989c, | ||
59 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
60 | { 0, 0x989c, | ||
61 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
62 | { 0, 0x989c, | ||
63 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
64 | { 0, 0x989c, | ||
65 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
66 | { 0, 0x989c, | ||
67 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
68 | { 0, 0x989c, | ||
69 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
70 | { 0, 0x989c, | ||
71 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
72 | { 0, 0x989c, | ||
73 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
74 | { 0, 0x989c, | ||
75 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
76 | { 0, 0x989c, | ||
77 | { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, | ||
78 | { 0, 0x989c, | ||
79 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
80 | { 0, 0x989c, | ||
81 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
82 | { 0, 0x989c, | ||
83 | { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, | ||
84 | { 0, 0x989c, | ||
85 | { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, | ||
86 | { 0, 0x98d4, | ||
87 | { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, | ||
88 | { 1, 0x98d4, | ||
89 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | ||
90 | { 2, 0x98d4, | ||
91 | { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, | ||
92 | { 3, 0x98d8, | ||
93 | { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, | ||
94 | { 6, 0x989c, | ||
95 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
96 | { 6, 0x989c, | ||
97 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
98 | { 6, 0x989c, | ||
99 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
100 | { 6, 0x989c, | ||
101 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
102 | { 6, 0x989c, | ||
103 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
104 | { 6, 0x989c, | ||
105 | { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, | ||
106 | { 6, 0x989c, | ||
107 | { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, | ||
108 | { 6, 0x989c, | ||
109 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
110 | { 6, 0x989c, | ||
111 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
112 | { 6, 0x989c, | ||
113 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
114 | { 6, 0x989c, | ||
115 | { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, | ||
116 | { 6, 0x989c, | ||
117 | { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, | ||
118 | { 6, 0x989c, | ||
119 | { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, | ||
120 | { 6, 0x989c, | ||
121 | { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, | ||
122 | { 6, 0x989c, | ||
123 | { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, | ||
124 | { 6, 0x989c, | ||
125 | { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, | ||
126 | { 6, 0x98d4, | ||
127 | { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, | ||
128 | { 7, 0x989c, | ||
129 | { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, | ||
130 | { 7, 0x989c, | ||
131 | { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, | ||
132 | { 7, 0x989c, | ||
133 | { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, | ||
134 | { 7, 0x989c, | ||
135 | { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, | ||
136 | { 7, 0x989c, | ||
137 | { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, | ||
138 | { 7, 0x989c, | ||
139 | { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, | ||
140 | { 7, 0x989c, | ||
141 | { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, | ||
142 | { 7, 0x98cc, | ||
143 | { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, | ||
144 | }; | ||
145 | |||
146 | /* Initial RF Gain settings for RF5111 */ | ||
147 | static const struct ath5k_ini_rfgain rfgain_5111[] = { | ||
148 | /* 5Ghz 2Ghz */ | ||
149 | { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } }, | ||
150 | { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } }, | ||
151 | { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } }, | ||
152 | { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } }, | ||
153 | { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } }, | ||
154 | { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } }, | ||
155 | { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } }, | ||
156 | { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } }, | ||
157 | { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } }, | ||
158 | { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } }, | ||
159 | { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } }, | ||
160 | { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } }, | ||
161 | { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } }, | ||
162 | { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } }, | ||
163 | { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } }, | ||
164 | { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } }, | ||
165 | { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } }, | ||
166 | { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } }, | ||
167 | { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } }, | ||
168 | { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } }, | ||
169 | { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } }, | ||
170 | { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } }, | ||
171 | { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } }, | ||
172 | { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } }, | ||
173 | { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } }, | ||
174 | { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } }, | ||
175 | { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } }, | ||
176 | { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } }, | ||
177 | { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } }, | ||
178 | { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } }, | ||
179 | { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } }, | ||
180 | { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } }, | ||
181 | { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } }, | ||
182 | { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } }, | ||
183 | { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } }, | ||
184 | { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } }, | ||
185 | { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } }, | ||
186 | { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } }, | ||
187 | { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } }, | ||
188 | { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } }, | ||
189 | { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } }, | ||
190 | { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } }, | ||
191 | { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } }, | ||
192 | { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } }, | ||
193 | { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } }, | ||
194 | { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } }, | ||
195 | { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } }, | ||
196 | { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } }, | ||
197 | { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } }, | ||
198 | { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } }, | ||
199 | { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } }, | ||
200 | { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } }, | ||
201 | { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } }, | ||
202 | { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } }, | ||
203 | { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } }, | ||
204 | { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } }, | ||
205 | { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } }, | ||
206 | { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } }, | ||
207 | { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } }, | ||
208 | { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } }, | ||
209 | { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } }, | ||
210 | { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } }, | ||
211 | { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } }, | ||
212 | { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } }, | ||
213 | }; | ||
214 | |||
215 | static const struct ath5k_gain_opt rfgain_opt_5111 = { | ||
216 | 4, | ||
217 | 9, | ||
218 | { | ||
219 | { { 4, 1, 1, 1 }, 6 }, | ||
220 | { { 4, 0, 1, 1 }, 4 }, | ||
221 | { { 3, 1, 1, 1 }, 3 }, | ||
222 | { { 4, 0, 0, 1 }, 1 }, | ||
223 | { { 4, 1, 1, 0 }, 0 }, | ||
224 | { { 4, 0, 1, 0 }, -2 }, | ||
225 | { { 3, 1, 1, 0 }, -3 }, | ||
226 | { { 4, 0, 0, 0 }, -4 }, | ||
227 | { { 2, 1, 1, 0 }, -6 } | ||
228 | } | ||
229 | }; | ||
230 | |||
231 | /* RF5112 mode-specific init registers */ | ||
232 | static const struct ath5k_ini_rf rfregs_5112[] = { | ||
233 | { 1, 0x98d4, | ||
234 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | ||
235 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | ||
236 | { 2, 0x98d0, | ||
237 | { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, | ||
238 | { 3, 0x98dc, | ||
239 | { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, | ||
240 | { 6, 0x989c, | ||
241 | { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, | ||
242 | { 6, 0x989c, | ||
243 | { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, | ||
244 | { 6, 0x989c, | ||
245 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
246 | { 6, 0x989c, | ||
247 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
248 | { 6, 0x989c, | ||
249 | { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, | ||
250 | { 6, 0x989c, | ||
251 | { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, | ||
252 | { 6, 0x989c, | ||
253 | { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, | ||
254 | { 6, 0x989c, | ||
255 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | ||
256 | { 6, 0x989c, | ||
257 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | ||
258 | { 6, 0x989c, | ||
259 | { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, | ||
260 | { 6, 0x989c, | ||
261 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
262 | { 6, 0x989c, | ||
263 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | ||
264 | { 6, 0x989c, | ||
265 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
266 | { 6, 0x989c, | ||
267 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
268 | { 6, 0x989c, | ||
269 | { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, | ||
270 | { 6, 0x989c, | ||
271 | { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, | ||
272 | { 6, 0x989c, | ||
273 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | ||
274 | { 6, 0x989c, | ||
275 | { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, | ||
276 | { 6, 0x989c, | ||
277 | { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, | ||
278 | { 6, 0x989c, | ||
279 | { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, | ||
280 | { 6, 0x989c, | ||
281 | { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, | ||
282 | { 6, 0x989c, | ||
283 | { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, | ||
284 | { 6, 0x989c, | ||
285 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | ||
286 | { 6, 0x989c, | ||
287 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | ||
288 | { 6, 0x989c, | ||
289 | { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, | ||
290 | { 6, 0x989c, | ||
291 | { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, | ||
292 | { 6, 0x989c, | ||
293 | { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, | ||
294 | { 6, 0x989c, | ||
295 | { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, | ||
296 | { 6, 0x989c, | ||
297 | { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, | ||
298 | { 6, 0x989c, | ||
299 | { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, | ||
300 | { 6, 0x989c, | ||
301 | { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, | ||
302 | { 6, 0x989c, | ||
303 | { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, | ||
304 | { 6, 0x989c, | ||
305 | { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, | ||
306 | { 6, 0x989c, | ||
307 | { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, | ||
308 | { 6, 0x989c, | ||
309 | { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, | ||
310 | { 6, 0x989c, | ||
311 | { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, | ||
312 | { 6, 0x989c, | ||
313 | { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, | ||
314 | { 6, 0x98d0, | ||
315 | { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, | ||
316 | { 7, 0x989c, | ||
317 | { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, | ||
318 | { 7, 0x989c, | ||
319 | { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, | ||
320 | { 7, 0x989c, | ||
321 | { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, | ||
322 | { 7, 0x989c, | ||
323 | { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, | ||
324 | { 7, 0x989c, | ||
325 | { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, | ||
326 | { 7, 0x989c, | ||
327 | { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, | ||
328 | { 7, 0x989c, | ||
329 | { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, | ||
330 | { 7, 0x989c, | ||
331 | { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, | ||
332 | { 7, 0x989c, | ||
333 | { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, | ||
334 | { 7, 0x989c, | ||
335 | { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, | ||
336 | { 7, 0x989c, | ||
337 | { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, | ||
338 | { 7, 0x989c, | ||
339 | { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, | ||
340 | { 7, 0x98c4, | ||
341 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
342 | }; | ||
343 | |||
344 | /* RF5112A mode-specific init registers */ | ||
345 | static const struct ath5k_ini_rf rfregs_5112a[] = { | ||
346 | { 1, 0x98d4, | ||
347 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | ||
348 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | ||
349 | { 2, 0x98d0, | ||
350 | { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, | ||
351 | { 3, 0x98dc, | ||
352 | { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, | ||
353 | { 6, 0x989c, | ||
354 | { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, | ||
355 | { 6, 0x989c, | ||
356 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
357 | { 6, 0x989c, | ||
358 | { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, | ||
359 | { 6, 0x989c, | ||
360 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | ||
361 | { 6, 0x989c, | ||
362 | { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, | ||
363 | { 6, 0x989c, | ||
364 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
365 | { 6, 0x989c, | ||
366 | { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, | ||
367 | { 6, 0x989c, | ||
368 | { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, | ||
369 | { 6, 0x989c, | ||
370 | { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, | ||
371 | { 6, 0x989c, | ||
372 | { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, | ||
373 | { 6, 0x989c, | ||
374 | { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, | ||
375 | { 6, 0x989c, | ||
376 | { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, | ||
377 | { 6, 0x989c, | ||
378 | { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, | ||
379 | { 6, 0x989c, | ||
380 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
381 | { 6, 0x989c, | ||
382 | { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, | ||
383 | { 6, 0x989c, | ||
384 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
385 | { 6, 0x989c, | ||
386 | { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, | ||
387 | { 6, 0x989c, | ||
388 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | ||
389 | { 6, 0x989c, | ||
390 | { 0x00190000, 0x00190000, 0x00190000, 0x00190000, 0x00190000 } }, | ||
391 | { 6, 0x989c, | ||
392 | { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, | ||
393 | { 6, 0x989c, | ||
394 | { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, | ||
395 | { 6, 0x989c, | ||
396 | { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, | ||
397 | { 6, 0x989c, | ||
398 | { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, | ||
399 | { 6, 0x989c, | ||
400 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | ||
401 | { 6, 0x989c, | ||
402 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | ||
403 | { 6, 0x989c, | ||
404 | { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, | ||
405 | { 6, 0x989c, | ||
406 | { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, | ||
407 | { 6, 0x989c, | ||
408 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | ||
409 | { 6, 0x989c, | ||
410 | { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, | ||
411 | { 6, 0x989c, | ||
412 | { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, | ||
413 | { 6, 0x989c, | ||
414 | { 0x00020080, 0x00020080, 0x00020080, 0x00020080, 0x00020080 } }, | ||
415 | { 6, 0x989c, | ||
416 | { 0x00080009, 0x00080009, 0x00080009, 0x00080009, 0x00080009 } }, | ||
417 | { 6, 0x989c, | ||
418 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
419 | { 6, 0x989c, | ||
420 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
421 | { 6, 0x989c, | ||
422 | { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, | ||
423 | { 6, 0x989c, | ||
424 | { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, | ||
425 | { 6, 0x989c, | ||
426 | { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, | ||
427 | { 6, 0x989c, | ||
428 | { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, | ||
429 | { 6, 0x989c, | ||
430 | { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, | ||
431 | { 6, 0x98d8, | ||
432 | { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, | ||
433 | { 7, 0x989c, | ||
434 | { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, | ||
435 | { 7, 0x989c, | ||
436 | { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, | ||
437 | { 7, 0x989c, | ||
438 | { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, | ||
439 | { 7, 0x989c, | ||
440 | { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, | ||
441 | { 7, 0x989c, | ||
442 | { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, | ||
443 | { 7, 0x989c, | ||
444 | { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, | ||
445 | { 7, 0x989c, | ||
446 | { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, | ||
447 | { 7, 0x989c, | ||
448 | { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, | ||
449 | { 7, 0x989c, | ||
450 | { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, | ||
451 | { 7, 0x989c, | ||
452 | { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, | ||
453 | { 7, 0x989c, | ||
454 | { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, | ||
455 | { 7, 0x989c, | ||
456 | { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, | ||
457 | { 7, 0x98c4, | ||
458 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
459 | }; | ||
460 | |||
461 | |||
462 | static const struct ath5k_ini_rf rfregs_2112a[] = { | ||
463 | { 1, AR5K_RF_BUFFER_CONTROL_4, | ||
464 | /* mode b mode g mode gTurbo */ | ||
465 | { 0x00000020, 0x00000020, 0x00000020 } }, | ||
466 | { 2, AR5K_RF_BUFFER_CONTROL_3, | ||
467 | { 0x03060408, 0x03060408, 0x03070408 } }, | ||
468 | { 3, AR5K_RF_BUFFER_CONTROL_6, | ||
469 | { 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | ||
470 | { 6, AR5K_RF_BUFFER, | ||
471 | { 0x0a000000, 0x0a000000, 0x0a000000 } }, | ||
472 | { 6, AR5K_RF_BUFFER, | ||
473 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
474 | { 6, AR5K_RF_BUFFER, | ||
475 | { 0x00800000, 0x00800000, 0x00800000 } }, | ||
476 | { 6, AR5K_RF_BUFFER, | ||
477 | { 0x002a0000, 0x002a0000, 0x002a0000 } }, | ||
478 | { 6, AR5K_RF_BUFFER, | ||
479 | { 0x00010000, 0x00010000, 0x00010000 } }, | ||
480 | { 6, AR5K_RF_BUFFER, | ||
481 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
482 | { 6, AR5K_RF_BUFFER, | ||
483 | { 0x00180000, 0x00180000, 0x00180000 } }, | ||
484 | { 6, AR5K_RF_BUFFER, | ||
485 | { 0x006e0000, 0x006e0000, 0x006e0000 } }, | ||
486 | { 6, AR5K_RF_BUFFER, | ||
487 | { 0x00c70000, 0x00c70000, 0x00c70000 } }, | ||
488 | { 6, AR5K_RF_BUFFER, | ||
489 | { 0x004b0000, 0x004b0000, 0x004b0000 } }, | ||
490 | { 6, AR5K_RF_BUFFER, | ||
491 | { 0x04480000, 0x04480000, 0x04480000 } }, | ||
492 | { 6, AR5K_RF_BUFFER, | ||
493 | { 0x002a0000, 0x002a0000, 0x002a0000 } }, | ||
494 | { 6, AR5K_RF_BUFFER, | ||
495 | { 0x00e40000, 0x00e40000, 0x00e40000 } }, | ||
496 | { 6, AR5K_RF_BUFFER, | ||
497 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
498 | { 6, AR5K_RF_BUFFER, | ||
499 | { 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, | ||
500 | { 6, AR5K_RF_BUFFER, | ||
501 | { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
502 | { 6, AR5K_RF_BUFFER, | ||
503 | { 0x043f0000, 0x043f0000, 0x043f0000 } }, | ||
504 | { 6, AR5K_RF_BUFFER, | ||
505 | { 0x0c0c0000, 0x0c0c0000, 0x0c0c0000 } }, | ||
506 | { 6, AR5K_RF_BUFFER, | ||
507 | { 0x02190000, 0x02190000, 0x02190000 } }, | ||
508 | { 6, AR5K_RF_BUFFER, | ||
509 | { 0x00240000, 0x00240000, 0x00240000 } }, | ||
510 | { 6, AR5K_RF_BUFFER, | ||
511 | { 0x00b40000, 0x00b40000, 0x00b40000 } }, | ||
512 | { 6, AR5K_RF_BUFFER, | ||
513 | { 0x00990000, 0x00990000, 0x00990000 } }, | ||
514 | { 6, AR5K_RF_BUFFER, | ||
515 | { 0x00500000, 0x00500000, 0x00500000 } }, | ||
516 | { 6, AR5K_RF_BUFFER, | ||
517 | { 0x002a0000, 0x002a0000, 0x002a0000 } }, | ||
518 | { 6, AR5K_RF_BUFFER, | ||
519 | { 0x00120000, 0x00120000, 0x00120000 } }, | ||
520 | { 6, AR5K_RF_BUFFER, | ||
521 | { 0xc0320000, 0xc0320000, 0xc0320000 } }, | ||
522 | { 6, AR5K_RF_BUFFER, | ||
523 | { 0x01740000, 0x01740000, 0x01740000 } }, | ||
524 | { 6, AR5K_RF_BUFFER, | ||
525 | { 0x00110000, 0x00110000, 0x00110000 } }, | ||
526 | { 6, AR5K_RF_BUFFER, | ||
527 | { 0x86280000, 0x86280000, 0x86280000 } }, | ||
528 | { 6, AR5K_RF_BUFFER, | ||
529 | { 0x31840000, 0x31840000, 0x31840000 } }, | ||
530 | { 6, AR5K_RF_BUFFER, | ||
531 | { 0x00f20080, 0x00f20080, 0x00f20080 } }, | ||
532 | { 6, AR5K_RF_BUFFER, | ||
533 | { 0x00070019, 0x00070019, 0x00070019 } }, | ||
534 | { 6, AR5K_RF_BUFFER, | ||
535 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
536 | { 6, AR5K_RF_BUFFER, | ||
537 | { 0x00000000, 0x00000000, 0x00000000 } }, | ||
538 | { 6, AR5K_RF_BUFFER, | ||
539 | { 0x000000b2, 0x000000b2, 0x000000b2 } }, | ||
540 | { 6, AR5K_RF_BUFFER, | ||
541 | { 0x00b02184, 0x00b02184, 0x00b02184 } }, | ||
542 | { 6, AR5K_RF_BUFFER, | ||
543 | { 0x004125a4, 0x004125a4, 0x004125a4 } }, | ||
544 | { 6, AR5K_RF_BUFFER, | ||
545 | { 0x00119220, 0x00119220, 0x00119220 } }, | ||
546 | { 6, AR5K_RF_BUFFER, | ||
547 | { 0x001a4800, 0x001a4800, 0x001a4800 } }, | ||
548 | { 6, AR5K_RF_BUFFER_CONTROL_5, | ||
549 | { 0x000b0230, 0x000b0230, 0x000b0230 } }, | ||
550 | { 7, AR5K_RF_BUFFER, | ||
551 | { 0x00000094, 0x00000094, 0x00000094 } }, | ||
552 | { 7, AR5K_RF_BUFFER, | ||
553 | { 0x00000091, 0x00000091, 0x00000091 } }, | ||
554 | { 7, AR5K_RF_BUFFER, | ||
555 | { 0x00000012, 0x00000012, 0x00000012 } }, | ||
556 | { 7, AR5K_RF_BUFFER, | ||
557 | { 0x00000080, 0x00000080, 0x00000080 } }, | ||
558 | { 7, AR5K_RF_BUFFER, | ||
559 | { 0x000000d9, 0x000000d9, 0x000000d9 } }, | ||
560 | { 7, AR5K_RF_BUFFER, | ||
561 | { 0x00000060, 0x00000060, 0x00000060 } }, | ||
562 | { 7, AR5K_RF_BUFFER, | ||
563 | { 0x000000f0, 0x000000f0, 0x000000f0 } }, | ||
564 | { 7, AR5K_RF_BUFFER, | ||
565 | { 0x000000a2, 0x000000a2, 0x000000a2 } }, | ||
566 | { 7, AR5K_RF_BUFFER, | ||
567 | { 0x00000052, 0x00000052, 0x00000052 } }, | ||
568 | { 7, AR5K_RF_BUFFER, | ||
569 | { 0x000000d4, 0x000000d4, 0x000000d4 } }, | ||
570 | { 7, AR5K_RF_BUFFER, | ||
571 | { 0x000014cc, 0x000014cc, 0x000014cc } }, | ||
572 | { 7, AR5K_RF_BUFFER, | ||
573 | { 0x0000048c, 0x0000048c, 0x0000048c } }, | ||
574 | { 7, AR5K_RF_BUFFER_CONTROL_1, | ||
575 | { 0x00000003, 0x00000003, 0x00000003 } }, | ||
576 | }; | ||
577 | |||
578 | /* RF5413/5414 mode-specific init registers */ | ||
579 | static const struct ath5k_ini_rf rfregs_5413[] = { | ||
580 | { 1, 0x98d4, | ||
581 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | ||
582 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | ||
583 | { 2, 0x98d0, | ||
584 | { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, | ||
585 | { 3, 0x98dc, | ||
586 | { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, | ||
587 | { 6, 0x989c, | ||
588 | { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, | ||
589 | { 6, 0x989c, | ||
590 | { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, | ||
591 | { 6, 0x989c, | ||
592 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
593 | { 6, 0x989c, | ||
594 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
595 | { 6, 0x989c, | ||
596 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
597 | { 6, 0x989c, | ||
598 | { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, | ||
599 | { 6, 0x989c, | ||
600 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
601 | { 6, 0x989c, | ||
602 | { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, | ||
603 | { 6, 0x989c, | ||
604 | { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, | ||
605 | { 6, 0x989c, | ||
606 | { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, | ||
607 | { 6, 0x989c, | ||
608 | { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, | ||
609 | { 6, 0x989c, | ||
610 | { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, | ||
611 | { 6, 0x989c, | ||
612 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
613 | { 6, 0x989c, | ||
614 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
615 | { 6, 0x989c, | ||
616 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
617 | { 6, 0x989c, | ||
618 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | ||
619 | { 6, 0x989c, | ||
620 | { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, | ||
621 | { 6, 0x989c, | ||
622 | { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, | ||
623 | { 6, 0x989c, | ||
624 | { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, | ||
625 | { 6, 0x989c, | ||
626 | { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, | ||
627 | { 6, 0x989c, | ||
628 | { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, | ||
629 | { 6, 0x989c, | ||
630 | { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, | ||
631 | { 6, 0x989c, | ||
632 | { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, | ||
633 | { 6, 0x989c, | ||
634 | { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, | ||
635 | { 6, 0x989c, | ||
636 | { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, | ||
637 | { 6, 0x989c, | ||
638 | { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, | ||
639 | { 6, 0x989c, | ||
640 | { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, | ||
641 | { 6, 0x989c, | ||
642 | { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, | ||
643 | { 6, 0x989c, | ||
644 | { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, | ||
645 | { 6, 0x989c, | ||
646 | { 0x00510040, 0x00510040, 0x005100a0, 0x005100a0, 0x005100a0 } }, | ||
647 | { 6, 0x989c, | ||
648 | { 0x0050006a, 0x0050006a, 0x005000dd, 0x005000dd, 0x005000dd } }, | ||
649 | { 6, 0x989c, | ||
650 | { 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000 } }, | ||
651 | { 6, 0x989c, | ||
652 | { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, | ||
653 | { 6, 0x989c, | ||
654 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
655 | { 6, 0x989c, | ||
656 | { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, | ||
657 | { 6, 0x989c, | ||
658 | { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00003600 } }, | ||
659 | { 6, 0x98c8, | ||
660 | { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, | ||
661 | { 7, 0x989c, | ||
662 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
663 | { 7, 0x989c, | ||
664 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
665 | { 7, 0x98cc, | ||
666 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
667 | }; | ||
668 | |||
669 | |||
670 | /* Initial RF Gain settings for RF5112 */ | ||
671 | static const struct ath5k_ini_rfgain rfgain_5112[] = { | ||
672 | /* 5Ghz 2Ghz */ | ||
673 | { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } }, | ||
674 | { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } }, | ||
675 | { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } }, | ||
676 | { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } }, | ||
677 | { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } }, | ||
678 | { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } }, | ||
679 | { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } }, | ||
680 | { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } }, | ||
681 | { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } }, | ||
682 | { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } }, | ||
683 | { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } }, | ||
684 | { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } }, | ||
685 | { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } }, | ||
686 | { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } }, | ||
687 | { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } }, | ||
688 | { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } }, | ||
689 | { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } }, | ||
690 | { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } }, | ||
691 | { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } }, | ||
692 | { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } }, | ||
693 | { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } }, | ||
694 | { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } }, | ||
695 | { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } }, | ||
696 | { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } }, | ||
697 | { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } }, | ||
698 | { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } }, | ||
699 | { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } }, | ||
700 | { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } }, | ||
701 | { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } }, | ||
702 | { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } }, | ||
703 | { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } }, | ||
704 | { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } }, | ||
705 | { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } }, | ||
706 | { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } }, | ||
707 | { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } }, | ||
708 | { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } }, | ||
709 | { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } }, | ||
710 | { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } }, | ||
711 | { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } }, | ||
712 | { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } }, | ||
713 | { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } }, | ||
714 | { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } }, | ||
715 | { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } }, | ||
716 | { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } }, | ||
717 | { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } }, | ||
718 | { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } }, | ||
719 | { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } }, | ||
720 | { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } }, | ||
721 | { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } }, | ||
722 | { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } }, | ||
723 | { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } }, | ||
724 | { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } }, | ||
725 | { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } }, | ||
726 | { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } }, | ||
727 | { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } }, | ||
728 | { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } }, | ||
729 | { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } }, | ||
730 | { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } }, | ||
731 | { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } }, | ||
732 | { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } }, | ||
733 | { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } }, | ||
734 | { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } }, | ||
735 | { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } }, | ||
736 | { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } }, | ||
737 | }; | ||
738 | |||
739 | /* Initial RF Gain settings for RF5413 */ | ||
740 | static const struct ath5k_ini_rfgain rfgain_5413[] = { | ||
741 | /* 5Ghz 2Ghz */ | ||
742 | { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, | ||
743 | { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } }, | ||
744 | { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } }, | ||
745 | { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } }, | ||
746 | { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } }, | ||
747 | { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } }, | ||
748 | { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } }, | ||
749 | { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } }, | ||
750 | { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } }, | ||
751 | { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } }, | ||
752 | { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } }, | ||
753 | { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } }, | ||
754 | { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } }, | ||
755 | { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } }, | ||
756 | { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } }, | ||
757 | { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } }, | ||
758 | { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } }, | ||
759 | { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } }, | ||
760 | { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } }, | ||
761 | { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } }, | ||
762 | { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } }, | ||
763 | { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } }, | ||
764 | { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } }, | ||
765 | { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } }, | ||
766 | { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } }, | ||
767 | { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } }, | ||
768 | { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } }, | ||
769 | { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } }, | ||
770 | { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } }, | ||
771 | { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } }, | ||
772 | { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } }, | ||
773 | { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } }, | ||
774 | { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } }, | ||
775 | { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } }, | ||
776 | { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } }, | ||
777 | { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } }, | ||
778 | { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } }, | ||
779 | { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } }, | ||
780 | { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } }, | ||
781 | { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } }, | ||
782 | { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } }, | ||
783 | { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } }, | ||
784 | { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } }, | ||
785 | { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } }, | ||
786 | { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } }, | ||
787 | { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } }, | ||
788 | { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } }, | ||
789 | { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } }, | ||
790 | { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } }, | ||
791 | { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } }, | ||
792 | { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } }, | ||
793 | { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } }, | ||
794 | { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } }, | ||
795 | { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } }, | ||
796 | { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } }, | ||
797 | { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } }, | ||
798 | { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } }, | ||
799 | { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } }, | ||
800 | { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } }, | ||
801 | { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } }, | ||
802 | { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } }, | ||
803 | { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } }, | ||
804 | { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } }, | ||
805 | { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, | ||
806 | }; | ||
807 | |||
808 | static const struct ath5k_gain_opt rfgain_opt_5112 = { | ||
809 | 1, | ||
810 | 8, | ||
811 | { | ||
812 | { { 3, 0, 0, 0, 0, 0, 0 }, 6 }, | ||
813 | { { 2, 0, 0, 0, 0, 0, 0 }, 0 }, | ||
814 | { { 1, 0, 0, 0, 0, 0, 0 }, -3 }, | ||
815 | { { 0, 0, 0, 0, 0, 0, 0 }, -6 }, | ||
816 | { { 0, 1, 1, 0, 0, 0, 0 }, -8 }, | ||
817 | { { 0, 1, 1, 0, 1, 1, 0 }, -10 }, | ||
818 | { { 0, 1, 0, 1, 1, 1, 0 }, -13 }, | ||
819 | { { 0, 1, 0, 1, 1, 0, 1 }, -16 }, | ||
820 | } | ||
821 | }; | ||
822 | |||
823 | /* | ||
824 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | ||
825 | */ | ||
826 | static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits, | ||
827 | u32 first, u32 col, bool set) | ||
828 | { | ||
829 | u32 mask, entry, last, data, shift, position; | ||
830 | s32 left; | ||
831 | int i; | ||
832 | |||
833 | data = 0; | ||
834 | |||
835 | if (rf == NULL) | ||
836 | /* should not happen */ | ||
837 | return 0; | ||
838 | |||
839 | if (!(col <= 3 && bits <= 32 && first + bits <= 319)) { | ||
840 | ATH5K_PRINTF("invalid values at offset %u\n", offset); | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | entry = ((first - 1) / 8) + offset; | ||
845 | position = (first - 1) % 8; | ||
846 | |||
847 | if (set == true) | ||
848 | data = ath5k_hw_bitswap(reg, bits); | ||
849 | |||
850 | for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) { | ||
851 | last = (position + left > 8) ? 8 : position + left; | ||
852 | mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8); | ||
853 | |||
854 | if (set == true) { | ||
855 | rf[entry] &= ~mask; | ||
856 | rf[entry] |= ((data << position) << (col * 8)) & mask; | ||
857 | data >>= (8 - position); | ||
858 | } else { | ||
859 | data = (((rf[entry] & mask) >> (col * 8)) >> position) | ||
860 | << shift; | ||
861 | shift += last - position; | ||
862 | } | ||
863 | |||
864 | left -= 8 - position; | ||
865 | } | ||
866 | |||
867 | data = set == true ? 1 : ath5k_hw_bitswap(data, bits); | ||
868 | |||
869 | return data; | ||
870 | } | ||
871 | |||
872 | static u32 ath5k_hw_rfregs_gainf_corr(struct ath5k_hw *ah) | ||
873 | { | ||
874 | u32 mix, step; | ||
875 | u32 *rf; | ||
876 | |||
877 | if (ah->ah_rf_banks == NULL) | ||
878 | return 0; | ||
879 | |||
880 | rf = ah->ah_rf_banks; | ||
881 | ah->ah_gain.g_f_corr = 0; | ||
882 | |||
883 | if (ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, false) != 1) | ||
884 | return 0; | ||
885 | |||
886 | step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 4, 32, 0, false); | ||
887 | mix = ah->ah_gain.g_step->gos_param[0]; | ||
888 | |||
889 | switch (mix) { | ||
890 | case 3: | ||
891 | ah->ah_gain.g_f_corr = step * 2; | ||
892 | break; | ||
893 | case 2: | ||
894 | ah->ah_gain.g_f_corr = (step - 5) * 2; | ||
895 | break; | ||
896 | case 1: | ||
897 | ah->ah_gain.g_f_corr = step; | ||
898 | break; | ||
899 | default: | ||
900 | ah->ah_gain.g_f_corr = 0; | ||
901 | break; | ||
902 | } | ||
903 | |||
904 | return ah->ah_gain.g_f_corr; | ||
905 | } | ||
906 | |||
907 | static bool ath5k_hw_rfregs_gain_readback(struct ath5k_hw *ah) | ||
908 | { | ||
909 | u32 step, mix, level[4]; | ||
910 | u32 *rf; | ||
911 | |||
912 | if (ah->ah_rf_banks == NULL) | ||
913 | return false; | ||
914 | |||
915 | rf = ah->ah_rf_banks; | ||
916 | |||
917 | if (ah->ah_radio == AR5K_RF5111) { | ||
918 | step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 6, 37, 0, | ||
919 | false); | ||
920 | level[0] = 0; | ||
921 | level[1] = (step == 0x3f) ? 0x32 : step + 4; | ||
922 | level[2] = (step != 0x3f) ? 0x40 : level[0]; | ||
923 | level[3] = level[2] + 0x32; | ||
924 | |||
925 | ah->ah_gain.g_high = level[3] - | ||
926 | (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5); | ||
927 | ah->ah_gain.g_low = level[0] + | ||
928 | (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); | ||
929 | } else { | ||
930 | mix = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, | ||
931 | false); | ||
932 | level[0] = level[2] = 0; | ||
933 | |||
934 | if (mix == 1) { | ||
935 | level[1] = level[3] = 83; | ||
936 | } else { | ||
937 | level[1] = level[3] = 107; | ||
938 | ah->ah_gain.g_high = 55; | ||
939 | } | ||
940 | } | ||
941 | |||
942 | return (ah->ah_gain.g_current >= level[0] && | ||
943 | ah->ah_gain.g_current <= level[1]) || | ||
944 | (ah->ah_gain.g_current >= level[2] && | ||
945 | ah->ah_gain.g_current <= level[3]); | ||
946 | } | ||
947 | |||
948 | static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah) | ||
949 | { | ||
950 | const struct ath5k_gain_opt *go; | ||
951 | int ret = 0; | ||
952 | |||
953 | switch (ah->ah_radio) { | ||
954 | case AR5K_RF5111: | ||
955 | go = &rfgain_opt_5111; | ||
956 | break; | ||
957 | case AR5K_RF5112: | ||
958 | case AR5K_RF5413: /* ??? */ | ||
959 | go = &rfgain_opt_5112; | ||
960 | break; | ||
961 | default: | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | ah->ah_gain.g_step = &go->go_step[ah->ah_gain.g_step_idx]; | ||
966 | |||
967 | if (ah->ah_gain.g_current >= ah->ah_gain.g_high) { | ||
968 | if (ah->ah_gain.g_step_idx == 0) | ||
969 | return -1; | ||
970 | for (ah->ah_gain.g_target = ah->ah_gain.g_current; | ||
971 | ah->ah_gain.g_target >= ah->ah_gain.g_high && | ||
972 | ah->ah_gain.g_step_idx > 0; | ||
973 | ah->ah_gain.g_step = | ||
974 | &go->go_step[ah->ah_gain.g_step_idx]) | ||
975 | ah->ah_gain.g_target -= 2 * | ||
976 | (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain - | ||
977 | ah->ah_gain.g_step->gos_gain); | ||
978 | |||
979 | ret = 1; | ||
980 | goto done; | ||
981 | } | ||
982 | |||
983 | if (ah->ah_gain.g_current <= ah->ah_gain.g_low) { | ||
984 | if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1)) | ||
985 | return -2; | ||
986 | for (ah->ah_gain.g_target = ah->ah_gain.g_current; | ||
987 | ah->ah_gain.g_target <= ah->ah_gain.g_low && | ||
988 | ah->ah_gain.g_step_idx < go->go_steps_count-1; | ||
989 | ah->ah_gain.g_step = | ||
990 | &go->go_step[ah->ah_gain.g_step_idx]) | ||
991 | ah->ah_gain.g_target -= 2 * | ||
992 | (go->go_step[++ah->ah_gain.g_step_idx].gos_gain - | ||
993 | ah->ah_gain.g_step->gos_gain); | ||
994 | |||
995 | ret = 2; | ||
996 | goto done; | ||
997 | } | ||
998 | |||
999 | done: | ||
1000 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1001 | "ret %d, gain step %u, current gain %u, target gain %u\n", | ||
1002 | ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current, | ||
1003 | ah->ah_gain.g_target); | ||
1004 | |||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | /* | ||
1009 | * Read EEPROM Calibration data, modify RF Banks and Initialize RF5111 | ||
1010 | */ | ||
1011 | static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah, | ||
1012 | struct ieee80211_channel *channel, unsigned int mode) | ||
1013 | { | ||
1014 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1015 | u32 *rf; | ||
1016 | const unsigned int rf_size = ARRAY_SIZE(rfregs_5111); | ||
1017 | unsigned int i; | ||
1018 | int obdb = -1, bank = -1; | ||
1019 | u32 ee_mode; | ||
1020 | |||
1021 | AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); | ||
1022 | |||
1023 | rf = ah->ah_rf_banks; | ||
1024 | |||
1025 | /* Copy values to modify them */ | ||
1026 | for (i = 0; i < rf_size; i++) { | ||
1027 | if (rfregs_5111[i].rf_bank >= AR5K_RF5111_INI_RF_MAX_BANKS) { | ||
1028 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | if (bank != rfregs_5111[i].rf_bank) { | ||
1033 | bank = rfregs_5111[i].rf_bank; | ||
1034 | ah->ah_offset[bank] = i; | ||
1035 | } | ||
1036 | |||
1037 | rf[i] = rfregs_5111[i].rf_value[mode]; | ||
1038 | } | ||
1039 | |||
1040 | /* Modify bank 0 */ | ||
1041 | if (channel->val & CHANNEL_2GHZ) { | ||
1042 | if (channel->val & CHANNEL_CCK) | ||
1043 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1044 | else | ||
1045 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1046 | obdb = 0; | ||
1047 | |||
1048 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0], | ||
1049 | ee->ee_ob[ee_mode][obdb], 3, 119, 0, true)) | ||
1050 | return -EINVAL; | ||
1051 | |||
1052 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0], | ||
1053 | ee->ee_ob[ee_mode][obdb], 3, 122, 0, true)) | ||
1054 | return -EINVAL; | ||
1055 | |||
1056 | obdb = 1; | ||
1057 | /* Modify bank 6 */ | ||
1058 | } else { | ||
1059 | /* For 11a, Turbo and XR */ | ||
1060 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1061 | obdb = channel->freq >= 5725 ? 3 : | ||
1062 | (channel->freq >= 5500 ? 2 : | ||
1063 | (channel->freq >= 5260 ? 1 : | ||
1064 | (channel->freq > 4000 ? 0 : -1))); | ||
1065 | |||
1066 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1067 | ee->ee_pwd_84, 1, 51, 3, true)) | ||
1068 | return -EINVAL; | ||
1069 | |||
1070 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1071 | ee->ee_pwd_90, 1, 45, 3, true)) | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | |||
1075 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1076 | !ee->ee_xpd[ee_mode], 1, 95, 0, true)) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1080 | ee->ee_x_gain[ee_mode], 4, 96, 0, true)) | ||
1081 | return -EINVAL; | ||
1082 | |||
1083 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ? | ||
1084 | ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, true)) | ||
1085 | return -EINVAL; | ||
1086 | |||
1087 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ? | ||
1088 | ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, true)) | ||
1089 | return -EINVAL; | ||
1090 | |||
1091 | /* Modify bank 7 */ | ||
1092 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | ||
1093 | ee->ee_i_gain[ee_mode], 6, 29, 0, true)) | ||
1094 | return -EINVAL; | ||
1095 | |||
1096 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | ||
1097 | ee->ee_xpd[ee_mode], 1, 4, 0, true)) | ||
1098 | return -EINVAL; | ||
1099 | |||
1100 | /* Write RF values */ | ||
1101 | for (i = 0; i < rf_size; i++) { | ||
1102 | AR5K_REG_WAIT(i); | ||
1103 | ath5k_hw_reg_write(ah, rf[i], rfregs_5111[i].rf_register); | ||
1104 | } | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | /* | ||
1110 | * Read EEPROM Calibration data, modify RF Banks and Initialize RF5112 | ||
1111 | */ | ||
1112 | static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, | ||
1113 | struct ieee80211_channel *channel, unsigned int mode) | ||
1114 | { | ||
1115 | const struct ath5k_ini_rf *rf_ini; | ||
1116 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1117 | u32 *rf; | ||
1118 | unsigned int rf_size, i; | ||
1119 | int obdb = -1, bank = -1; | ||
1120 | u32 ee_mode; | ||
1121 | |||
1122 | AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); | ||
1123 | |||
1124 | rf = ah->ah_rf_banks; | ||
1125 | |||
1126 | if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A | ||
1127 | && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){ | ||
1128 | rf_ini = rfregs_2112a; | ||
1129 | rf_size = ARRAY_SIZE(rfregs_5112a); | ||
1130 | if (mode < 2) { | ||
1131 | ATH5K_ERR(ah->ah_sc,"invalid channel mode: %i\n",mode); | ||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | mode = mode - 2; /*no a/turboa modes for 2112*/ | ||
1135 | } else if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { | ||
1136 | rf_ini = rfregs_5112a; | ||
1137 | rf_size = ARRAY_SIZE(rfregs_5112a); | ||
1138 | } else { | ||
1139 | rf_ini = rfregs_5112; | ||
1140 | rf_size = ARRAY_SIZE(rfregs_5112); | ||
1141 | } | ||
1142 | |||
1143 | /* Copy values to modify them */ | ||
1144 | for (i = 0; i < rf_size; i++) { | ||
1145 | if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) { | ||
1146 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | ||
1147 | return -EINVAL; | ||
1148 | } | ||
1149 | |||
1150 | if (bank != rf_ini[i].rf_bank) { | ||
1151 | bank = rf_ini[i].rf_bank; | ||
1152 | ah->ah_offset[bank] = i; | ||
1153 | } | ||
1154 | |||
1155 | rf[i] = rf_ini[i].rf_value[mode]; | ||
1156 | } | ||
1157 | |||
1158 | /* Modify bank 6 */ | ||
1159 | if (channel->val & CHANNEL_2GHZ) { | ||
1160 | if (channel->val & CHANNEL_OFDM) | ||
1161 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1162 | else | ||
1163 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1164 | obdb = 0; | ||
1165 | |||
1166 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1167 | ee->ee_ob[ee_mode][obdb], 3, 287, 0, true)) | ||
1168 | return -EINVAL; | ||
1169 | |||
1170 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1171 | ee->ee_ob[ee_mode][obdb], 3, 290, 0, true)) | ||
1172 | return -EINVAL; | ||
1173 | } else { | ||
1174 | /* For 11a, Turbo and XR */ | ||
1175 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1176 | obdb = channel->freq >= 5725 ? 3 : | ||
1177 | (channel->freq >= 5500 ? 2 : | ||
1178 | (channel->freq >= 5260 ? 1 : | ||
1179 | (channel->freq > 4000 ? 0 : -1))); | ||
1180 | |||
1181 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1182 | ee->ee_ob[ee_mode][obdb], 3, 279, 0, true)) | ||
1183 | return -EINVAL; | ||
1184 | |||
1185 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1186 | ee->ee_ob[ee_mode][obdb], 3, 282, 0, true)) | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | |||
1190 | ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1191 | ee->ee_x_gain[ee_mode], 2, 270, 0, true); | ||
1192 | ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1193 | ee->ee_x_gain[ee_mode], 2, 257, 0, true); | ||
1194 | |||
1195 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
1196 | ee->ee_xpd[ee_mode], 1, 302, 0, true)) | ||
1197 | return -EINVAL; | ||
1198 | |||
1199 | /* Modify bank 7 */ | ||
1200 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | ||
1201 | ee->ee_i_gain[ee_mode], 6, 14, 0, true)) | ||
1202 | return -EINVAL; | ||
1203 | |||
1204 | /* Write RF values */ | ||
1205 | for (i = 0; i < rf_size; i++) | ||
1206 | ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register); | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1212 | * Initialize RF5413/5414 | ||
1213 | */ | ||
1214 | static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, | ||
1215 | struct ieee80211_channel *channel, unsigned int mode) | ||
1216 | { | ||
1217 | const struct ath5k_ini_rf *rf_ini; | ||
1218 | u32 *rf; | ||
1219 | unsigned int rf_size, i; | ||
1220 | int bank = -1; | ||
1221 | |||
1222 | AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); | ||
1223 | |||
1224 | rf = ah->ah_rf_banks; | ||
1225 | |||
1226 | rf_ini = rfregs_5413; | ||
1227 | rf_size = ARRAY_SIZE(rfregs_5413); | ||
1228 | |||
1229 | /* Copy values to modify them */ | ||
1230 | for (i = 0; i < rf_size; i++) { | ||
1231 | if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) { | ||
1232 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | ||
1233 | return -EINVAL; | ||
1234 | } | ||
1235 | |||
1236 | if (bank != rf_ini[i].rf_bank) { | ||
1237 | bank = rf_ini[i].rf_bank; | ||
1238 | ah->ah_offset[bank] = i; | ||
1239 | } | ||
1240 | |||
1241 | rf[i] = rf_ini[i].rf_value[mode]; | ||
1242 | } | ||
1243 | |||
1244 | /* | ||
1245 | * After compairing dumps from different cards | ||
1246 | * we get the same RF_BUFFER settings (diff returns | ||
1247 | * 0 lines). It seems that RF_BUFFER settings are static | ||
1248 | * and are written unmodified (no EEPROM stuff | ||
1249 | * is used because calibration data would be | ||
1250 | * different between different cards and would result | ||
1251 | * different RF_BUFFER settings) | ||
1252 | */ | ||
1253 | |||
1254 | /* Write RF values */ | ||
1255 | for (i = 0; i < rf_size; i++) | ||
1256 | ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register); | ||
1257 | |||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | /* | ||
1262 | * Initialize RF | ||
1263 | */ | ||
1264 | int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
1265 | unsigned int mode) | ||
1266 | { | ||
1267 | int (*func)(struct ath5k_hw *, struct ieee80211_channel *, unsigned int); | ||
1268 | int ret; | ||
1269 | |||
1270 | switch (ah->ah_radio) { | ||
1271 | case AR5K_RF5111: | ||
1272 | ah->ah_rf_banks_size = sizeof(rfregs_5111); | ||
1273 | func = ath5k_hw_rf5111_rfregs; | ||
1274 | break; | ||
1275 | case AR5K_RF5112: | ||
1276 | if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) | ||
1277 | ah->ah_rf_banks_size = sizeof(rfregs_5112a); | ||
1278 | else | ||
1279 | ah->ah_rf_banks_size = sizeof(rfregs_5112); | ||
1280 | func = ath5k_hw_rf5112_rfregs; | ||
1281 | break; | ||
1282 | case AR5K_RF5413: | ||
1283 | ah->ah_rf_banks_size = sizeof(rfregs_5413); | ||
1284 | func = ath5k_hw_rf5413_rfregs; | ||
1285 | break; | ||
1286 | default: | ||
1287 | return -EINVAL; | ||
1288 | } | ||
1289 | |||
1290 | if (ah->ah_rf_banks == NULL) { | ||
1291 | /* XXX do extra checks? */ | ||
1292 | ah->ah_rf_banks = kmalloc(ah->ah_rf_banks_size, GFP_KERNEL); | ||
1293 | if (ah->ah_rf_banks == NULL) { | ||
1294 | ATH5K_ERR(ah->ah_sc, "out of memory\n"); | ||
1295 | return -ENOMEM; | ||
1296 | } | ||
1297 | } | ||
1298 | |||
1299 | ret = func(ah, channel, mode); | ||
1300 | if (!ret) | ||
1301 | ah->ah_rf_gain = AR5K_RFGAIN_INACTIVE; | ||
1302 | |||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1306 | int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) | ||
1307 | { | ||
1308 | const struct ath5k_ini_rfgain *ath5k_rfg; | ||
1309 | unsigned int i, size; | ||
1310 | |||
1311 | switch (ah->ah_radio) { | ||
1312 | case AR5K_RF5111: | ||
1313 | ath5k_rfg = rfgain_5111; | ||
1314 | size = ARRAY_SIZE(rfgain_5111); | ||
1315 | break; | ||
1316 | case AR5K_RF5112: | ||
1317 | ath5k_rfg = rfgain_5112; | ||
1318 | size = ARRAY_SIZE(rfgain_5112); | ||
1319 | break; | ||
1320 | case AR5K_RF5413: | ||
1321 | ath5k_rfg = rfgain_5413; | ||
1322 | size = ARRAY_SIZE(rfgain_5413); | ||
1323 | break; | ||
1324 | default: | ||
1325 | return -EINVAL; | ||
1326 | } | ||
1327 | |||
1328 | switch (freq) { | ||
1329 | case AR5K_INI_RFGAIN_2GHZ: | ||
1330 | case AR5K_INI_RFGAIN_5GHZ: | ||
1331 | break; | ||
1332 | default: | ||
1333 | return -EINVAL; | ||
1334 | } | ||
1335 | |||
1336 | for (i = 0; i < size; i++) { | ||
1337 | AR5K_REG_WAIT(i); | ||
1338 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], | ||
1339 | (u32)ath5k_rfg[i].rfg_register); | ||
1340 | } | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah) | ||
1346 | { | ||
1347 | u32 data, type; | ||
1348 | |||
1349 | ATH5K_TRACE(ah->ah_sc); | ||
1350 | |||
1351 | if (ah->ah_rf_banks == NULL || !ah->ah_gain.g_active || | ||
1352 | ah->ah_version <= AR5K_AR5211) | ||
1353 | return AR5K_RFGAIN_INACTIVE; | ||
1354 | |||
1355 | if (ah->ah_rf_gain != AR5K_RFGAIN_READ_REQUESTED) | ||
1356 | goto done; | ||
1357 | |||
1358 | data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE); | ||
1359 | |||
1360 | if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) { | ||
1361 | ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S; | ||
1362 | type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE); | ||
1363 | |||
1364 | if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) | ||
1365 | ah->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR; | ||
1366 | |||
1367 | if (ah->ah_radio >= AR5K_RF5112) { | ||
1368 | ath5k_hw_rfregs_gainf_corr(ah); | ||
1369 | ah->ah_gain.g_current = | ||
1370 | ah->ah_gain.g_current>=ah->ah_gain.g_f_corr ? | ||
1371 | (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) : | ||
1372 | 0; | ||
1373 | } | ||
1374 | |||
1375 | if (ath5k_hw_rfregs_gain_readback(ah) && | ||
1376 | AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) && | ||
1377 | ath5k_hw_rfregs_gain_adjust(ah)) | ||
1378 | ah->ah_rf_gain = AR5K_RFGAIN_NEED_CHANGE; | ||
1379 | } | ||
1380 | |||
1381 | done: | ||
1382 | return ah->ah_rf_gain; | ||
1383 | } | ||
1384 | |||
1385 | int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah) | ||
1386 | { | ||
1387 | /* Initialize the gain optimization values */ | ||
1388 | switch (ah->ah_radio) { | ||
1389 | case AR5K_RF5111: | ||
1390 | ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default; | ||
1391 | ah->ah_gain.g_step = | ||
1392 | &rfgain_opt_5111.go_step[ah->ah_gain.g_step_idx]; | ||
1393 | ah->ah_gain.g_low = 20; | ||
1394 | ah->ah_gain.g_high = 35; | ||
1395 | ah->ah_gain.g_active = 1; | ||
1396 | break; | ||
1397 | case AR5K_RF5112: | ||
1398 | case AR5K_RF5413: /* ??? */ | ||
1399 | ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; | ||
1400 | ah->ah_gain.g_step = | ||
1401 | &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx]; | ||
1402 | ah->ah_gain.g_low = 20; | ||
1403 | ah->ah_gain.g_high = 85; | ||
1404 | ah->ah_gain.g_active = 1; | ||
1405 | break; | ||
1406 | default: | ||
1407 | return -EINVAL; | ||
1408 | } | ||
1409 | |||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | /**************************\ | ||
1414 | PHY/RF channel functions | ||
1415 | \**************************/ | ||
1416 | |||
1417 | /* | ||
1418 | * Check if a channel is supported | ||
1419 | */ | ||
1420 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
1421 | { | ||
1422 | /* Check if the channel is in our supported range */ | ||
1423 | if (flags & CHANNEL_2GHZ) { | ||
1424 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
1425 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
1426 | return true; | ||
1427 | } else if (flags & CHANNEL_5GHZ) | ||
1428 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
1429 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
1430 | return true; | ||
1431 | |||
1432 | return false; | ||
1433 | } | ||
1434 | |||
1435 | /* | ||
1436 | * Convertion needed for RF5110 | ||
1437 | */ | ||
1438 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | ||
1439 | { | ||
1440 | u32 athchan; | ||
1441 | |||
1442 | /* | ||
1443 | * Convert IEEE channel/MHz to an internal channel value used | ||
1444 | * by the AR5210 chipset. This has not been verified with | ||
1445 | * newer chipsets like the AR5212A who have a completely | ||
1446 | * different RF/PHY part. | ||
1447 | */ | ||
1448 | athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) | | ||
1449 | (1 << 6) | 0x1; | ||
1450 | |||
1451 | return athchan; | ||
1452 | } | ||
1453 | |||
1454 | /* | ||
1455 | * Set channel on RF5110 | ||
1456 | */ | ||
1457 | static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | ||
1458 | struct ieee80211_channel *channel) | ||
1459 | { | ||
1460 | u32 data; | ||
1461 | |||
1462 | /* | ||
1463 | * Set the channel and wait | ||
1464 | */ | ||
1465 | data = ath5k_hw_rf5110_chan2athchan(channel); | ||
1466 | ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); | ||
1467 | ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); | ||
1468 | mdelay(1); | ||
1469 | |||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | /* | ||
1474 | * Convertion needed for 5111 | ||
1475 | */ | ||
1476 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | ||
1477 | struct ath5k_athchan_2ghz *athchan) | ||
1478 | { | ||
1479 | int channel; | ||
1480 | |||
1481 | /* Cast this value to catch negative channel numbers (>= -19) */ | ||
1482 | channel = (int)ieee; | ||
1483 | |||
1484 | /* | ||
1485 | * Map 2GHz IEEE channel to 5GHz Atheros channel | ||
1486 | */ | ||
1487 | if (channel <= 13) { | ||
1488 | athchan->a2_athchan = 115 + channel; | ||
1489 | athchan->a2_flags = 0x46; | ||
1490 | } else if (channel == 14) { | ||
1491 | athchan->a2_athchan = 124; | ||
1492 | athchan->a2_flags = 0x44; | ||
1493 | } else if (channel >= 15 && channel <= 26) { | ||
1494 | athchan->a2_athchan = ((channel - 14) * 4) + 132; | ||
1495 | athchan->a2_flags = 0x46; | ||
1496 | } else | ||
1497 | return -EINVAL; | ||
1498 | |||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1502 | /* | ||
1503 | * Set channel on 5111 | ||
1504 | */ | ||
1505 | static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, | ||
1506 | struct ieee80211_channel *channel) | ||
1507 | { | ||
1508 | struct ath5k_athchan_2ghz ath5k_channel_2ghz; | ||
1509 | unsigned int ath5k_channel = channel->chan; | ||
1510 | u32 data0, data1, clock; | ||
1511 | int ret; | ||
1512 | |||
1513 | /* | ||
1514 | * Set the channel on the RF5111 radio | ||
1515 | */ | ||
1516 | data0 = data1 = 0; | ||
1517 | |||
1518 | if (channel->val & CHANNEL_2GHZ) { | ||
1519 | /* Map 2GHz channel to 5GHz Atheros channel ID */ | ||
1520 | ret = ath5k_hw_rf5111_chan2athchan(channel->chan, | ||
1521 | &ath5k_channel_2ghz); | ||
1522 | if (ret) | ||
1523 | return ret; | ||
1524 | |||
1525 | ath5k_channel = ath5k_channel_2ghz.a2_athchan; | ||
1526 | data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff) | ||
1527 | << 5) | (1 << 4); | ||
1528 | } | ||
1529 | |||
1530 | if (ath5k_channel < 145 || !(ath5k_channel & 1)) { | ||
1531 | clock = 1; | ||
1532 | data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) | | ||
1533 | (clock << 1) | (1 << 10) | 1; | ||
1534 | } else { | ||
1535 | clock = 0; | ||
1536 | data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff) | ||
1537 | << 2) | (clock << 1) | (1 << 10) | 1; | ||
1538 | } | ||
1539 | |||
1540 | ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8), | ||
1541 | AR5K_RF_BUFFER); | ||
1542 | ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00), | ||
1543 | AR5K_RF_BUFFER_CONTROL_3); | ||
1544 | |||
1545 | return 0; | ||
1546 | } | ||
1547 | |||
1548 | /* | ||
1549 | * Set channel on 5112 and newer | ||
1550 | */ | ||
1551 | static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | ||
1552 | struct ieee80211_channel *channel) | ||
1553 | { | ||
1554 | u32 data, data0, data1, data2; | ||
1555 | u16 c; | ||
1556 | |||
1557 | data = data0 = data1 = data2 = 0; | ||
1558 | c = channel->freq; | ||
1559 | |||
1560 | /* | ||
1561 | * Set the channel on the RF5112 or newer | ||
1562 | */ | ||
1563 | if (c < 4800) { | ||
1564 | if (!((c - 2224) % 5)) { | ||
1565 | data0 = ((2 * (c - 704)) - 3040) / 10; | ||
1566 | data1 = 1; | ||
1567 | } else if (!((c - 2192) % 5)) { | ||
1568 | data0 = ((2 * (c - 672)) - 3040) / 10; | ||
1569 | data1 = 0; | ||
1570 | } else | ||
1571 | return -EINVAL; | ||
1572 | |||
1573 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); | ||
1574 | } else { | ||
1575 | if (!(c % 20) && c >= 5120) { | ||
1576 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | ||
1577 | data2 = ath5k_hw_bitswap(3, 2); | ||
1578 | } else if (!(c % 10)) { | ||
1579 | data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); | ||
1580 | data2 = ath5k_hw_bitswap(2, 2); | ||
1581 | } else if (!(c % 5)) { | ||
1582 | data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); | ||
1583 | data2 = ath5k_hw_bitswap(1, 2); | ||
1584 | } else | ||
1585 | return -EINVAL; | ||
1586 | } | ||
1587 | |||
1588 | data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; | ||
1589 | |||
1590 | ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); | ||
1591 | ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); | ||
1592 | |||
1593 | return 0; | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1597 | * Set a channel on the radio chip | ||
1598 | */ | ||
1599 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | ||
1600 | { | ||
1601 | int ret; | ||
1602 | |||
1603 | /* | ||
1604 | * Check bounds supported by the PHY | ||
1605 | * (don't care about regulation restrictions at this point) | ||
1606 | */ | ||
1607 | if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min || | ||
1608 | channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) && | ||
1609 | (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min || | ||
1610 | channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) { | ||
1611 | ATH5K_ERR(ah->ah_sc, | ||
1612 | "channel out of supported range (%u MHz)\n", | ||
1613 | channel->freq); | ||
1614 | return -EINVAL; | ||
1615 | } | ||
1616 | |||
1617 | /* | ||
1618 | * Set the channel and wait | ||
1619 | */ | ||
1620 | switch (ah->ah_radio) { | ||
1621 | case AR5K_RF5110: | ||
1622 | ret = ath5k_hw_rf5110_channel(ah, channel); | ||
1623 | break; | ||
1624 | case AR5K_RF5111: | ||
1625 | ret = ath5k_hw_rf5111_channel(ah, channel); | ||
1626 | break; | ||
1627 | default: | ||
1628 | ret = ath5k_hw_rf5112_channel(ah, channel); | ||
1629 | break; | ||
1630 | } | ||
1631 | |||
1632 | if (ret) | ||
1633 | return ret; | ||
1634 | |||
1635 | ah->ah_current_channel.freq = channel->freq; | ||
1636 | ah->ah_current_channel.val = channel->val; | ||
1637 | ah->ah_turbo = channel->val == CHANNEL_T ? true : false; | ||
1638 | |||
1639 | return 0; | ||
1640 | } | ||
1641 | |||
1642 | /*****************\ | ||
1643 | PHY calibration | ||
1644 | \*****************/ | ||
1645 | |||
1646 | /** | ||
1647 | * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration | ||
1648 | * | ||
1649 | * @ah: struct ath5k_hw pointer we are operating on | ||
1650 | * @freq: the channel frequency, just used for error logging | ||
1651 | * | ||
1652 | * This function performs a noise floor calibration of the PHY and waits for | ||
1653 | * it to complete. Then the noise floor value is compared to some maximum | ||
1654 | * noise floor we consider valid. | ||
1655 | * | ||
1656 | * Note that this is different from what the madwifi HAL does: it reads the | ||
1657 | * noise floor and afterwards initiates the calibration. Since the noise floor | ||
1658 | * calibration can take some time to finish, depending on the current channel | ||
1659 | * use, that avoids the occasional timeout warnings we are seeing now. | ||
1660 | * | ||
1661 | * See the following link for an Atheros patent on noise floor calibration: | ||
1662 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ | ||
1663 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 | ||
1664 | * | ||
1665 | */ | ||
1666 | int | ||
1667 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | ||
1668 | { | ||
1669 | int ret; | ||
1670 | unsigned int i; | ||
1671 | s32 noise_floor; | ||
1672 | |||
1673 | /* | ||
1674 | * Enable noise floor calibration and wait until completion | ||
1675 | */ | ||
1676 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1677 | AR5K_PHY_AGCCTL_NF); | ||
1678 | |||
1679 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1680 | AR5K_PHY_AGCCTL_NF, 0, false); | ||
1681 | if (ret) { | ||
1682 | ATH5K_ERR(ah->ah_sc, | ||
1683 | "noise floor calibration timeout (%uMHz)\n", freq); | ||
1684 | return ret; | ||
1685 | } | ||
1686 | |||
1687 | /* Wait until the noise floor is calibrated and read the value */ | ||
1688 | for (i = 20; i > 0; i--) { | ||
1689 | mdelay(1); | ||
1690 | noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | ||
1691 | noise_floor = AR5K_PHY_NF_RVAL(noise_floor); | ||
1692 | if (noise_floor & AR5K_PHY_NF_ACTIVE) { | ||
1693 | noise_floor = AR5K_PHY_NF_AVAL(noise_floor); | ||
1694 | |||
1695 | if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) | ||
1696 | break; | ||
1697 | } | ||
1698 | } | ||
1699 | |||
1700 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1701 | "noise floor %d\n", noise_floor); | ||
1702 | |||
1703 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { | ||
1704 | ATH5K_ERR(ah->ah_sc, | ||
1705 | "noise floor calibration failed (%uMHz)\n", freq); | ||
1706 | return -EIO; | ||
1707 | } | ||
1708 | |||
1709 | ah->ah_noise_floor = noise_floor; | ||
1710 | |||
1711 | return 0; | ||
1712 | } | ||
1713 | |||
1714 | /* | ||
1715 | * Perform a PHY calibration on RF5110 | ||
1716 | * -Fix BPSK/QAM Constellation (I/Q correction) | ||
1717 | * -Calculate Noise Floor | ||
1718 | */ | ||
1719 | static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | ||
1720 | struct ieee80211_channel *channel) | ||
1721 | { | ||
1722 | u32 phy_sig, phy_agc, phy_sat, beacon; | ||
1723 | int ret; | ||
1724 | |||
1725 | /* | ||
1726 | * Disable beacons and RX/TX queues, wait | ||
1727 | */ | ||
1728 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, | ||
1729 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | ||
1730 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | ||
1731 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | ||
1732 | |||
1733 | udelay(2300); | ||
1734 | |||
1735 | /* | ||
1736 | * Set the channel (with AGC turned off) | ||
1737 | */ | ||
1738 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | ||
1739 | udelay(10); | ||
1740 | ret = ath5k_hw_channel(ah, channel); | ||
1741 | |||
1742 | /* | ||
1743 | * Activate PHY and wait | ||
1744 | */ | ||
1745 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
1746 | mdelay(1); | ||
1747 | |||
1748 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | ||
1749 | |||
1750 | if (ret) | ||
1751 | return ret; | ||
1752 | |||
1753 | /* | ||
1754 | * Calibrate the radio chip | ||
1755 | */ | ||
1756 | |||
1757 | /* Remember normal state */ | ||
1758 | phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG); | ||
1759 | phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE); | ||
1760 | phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT); | ||
1761 | |||
1762 | /* Update radio registers */ | ||
1763 | ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) | | ||
1764 | AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); | ||
1765 | |||
1766 | ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI | | ||
1767 | AR5K_PHY_AGCCOARSE_LO)) | | ||
1768 | AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) | | ||
1769 | AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); | ||
1770 | |||
1771 | ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT | | ||
1772 | AR5K_PHY_ADCSAT_THR)) | | ||
1773 | AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) | | ||
1774 | AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT); | ||
1775 | |||
1776 | udelay(20); | ||
1777 | |||
1778 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | ||
1779 | udelay(10); | ||
1780 | ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); | ||
1781 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); | ||
1782 | |||
1783 | mdelay(1); | ||
1784 | |||
1785 | /* | ||
1786 | * Enable calibration and wait until completion | ||
1787 | */ | ||
1788 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); | ||
1789 | |||
1790 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1791 | AR5K_PHY_AGCCTL_CAL, 0, false); | ||
1792 | |||
1793 | /* Reset to normal state */ | ||
1794 | ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG); | ||
1795 | ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE); | ||
1796 | ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT); | ||
1797 | |||
1798 | if (ret) { | ||
1799 | ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", | ||
1800 | channel->freq); | ||
1801 | return ret; | ||
1802 | } | ||
1803 | |||
1804 | ret = ath5k_hw_noise_floor_calibration(ah, channel->freq); | ||
1805 | if (ret) | ||
1806 | return ret; | ||
1807 | |||
1808 | /* | ||
1809 | * Re-enable RX/TX and beacons | ||
1810 | */ | ||
1811 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, | ||
1812 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | ||
1813 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); | ||
1814 | |||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1819 | * Perform a PHY calibration on RF5111/5112 | ||
1820 | */ | ||
1821 | static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | ||
1822 | struct ieee80211_channel *channel) | ||
1823 | { | ||
1824 | u32 i_pwr, q_pwr; | ||
1825 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; | ||
1826 | ATH5K_TRACE(ah->ah_sc); | ||
1827 | |||
1828 | if (ah->ah_calibration == false || | ||
1829 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) | ||
1830 | goto done; | ||
1831 | |||
1832 | ah->ah_calibration = false; | ||
1833 | |||
1834 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | ||
1835 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); | ||
1836 | q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); | ||
1837 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; | ||
1838 | q_coffd = q_pwr >> 6; | ||
1839 | |||
1840 | if (i_coffd == 0 || q_coffd == 0) | ||
1841 | goto done; | ||
1842 | |||
1843 | i_coff = ((-iq_corr) / i_coffd) & 0x3f; | ||
1844 | q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f; | ||
1845 | |||
1846 | /* Commit new IQ value */ | ||
1847 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | | ||
1848 | ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); | ||
1849 | |||
1850 | done: | ||
1851 | ath5k_hw_noise_floor_calibration(ah, channel->freq); | ||
1852 | |||
1853 | /* Request RF gain */ | ||
1854 | if (channel->val & CHANNEL_5GHZ) { | ||
1855 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max, | ||
1856 | AR5K_PHY_PAPD_PROBE_TXPOWER) | | ||
1857 | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); | ||
1858 | ah->ah_rf_gain = AR5K_RFGAIN_READ_REQUESTED; | ||
1859 | } | ||
1860 | |||
1861 | return 0; | ||
1862 | } | ||
1863 | |||
1864 | /* | ||
1865 | * Perform a PHY calibration | ||
1866 | */ | ||
1867 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | ||
1868 | struct ieee80211_channel *channel) | ||
1869 | { | ||
1870 | int ret; | ||
1871 | |||
1872 | if (ah->ah_radio == AR5K_RF5110) | ||
1873 | ret = ath5k_hw_rf5110_calibrate(ah, channel); | ||
1874 | else | ||
1875 | ret = ath5k_hw_rf511x_calibrate(ah, channel); | ||
1876 | |||
1877 | return ret; | ||
1878 | } | ||
1879 | |||
1880 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
1881 | { | ||
1882 | ATH5K_TRACE(ah->ah_sc); | ||
1883 | /*Just a try M.F.*/ | ||
1884 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1885 | |||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | /********************\ | ||
1890 | Misc PHY functions | ||
1891 | \********************/ | ||
1892 | |||
1893 | /* | ||
1894 | * Get the PHY Chip revision | ||
1895 | */ | ||
1896 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
1897 | { | ||
1898 | unsigned int i; | ||
1899 | u32 srev; | ||
1900 | u16 ret; | ||
1901 | |||
1902 | ATH5K_TRACE(ah->ah_sc); | ||
1903 | |||
1904 | /* | ||
1905 | * Set the radio chip access register | ||
1906 | */ | ||
1907 | switch (chan) { | ||
1908 | case CHANNEL_2GHZ: | ||
1909 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
1910 | break; | ||
1911 | case CHANNEL_5GHZ: | ||
1912 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1913 | break; | ||
1914 | default: | ||
1915 | return 0; | ||
1916 | } | ||
1917 | |||
1918 | mdelay(2); | ||
1919 | |||
1920 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
1921 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
1922 | |||
1923 | for (i = 0; i < 8; i++) | ||
1924 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
1925 | |||
1926 | if (ah->ah_version == AR5K_AR5210) { | ||
1927 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
1928 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
1929 | } else { | ||
1930 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
1931 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
1932 | ((srev & 0x0f) << 4), 8); | ||
1933 | } | ||
1934 | |||
1935 | /* Reset to the 5GHz mode */ | ||
1936 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1937 | |||
1938 | return ret; | ||
1939 | } | ||
1940 | |||
1941 | void /*TODO:Boundary check*/ | ||
1942 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) | ||
1943 | { | ||
1944 | ATH5K_TRACE(ah->ah_sc); | ||
1945 | /*Just a try M.F.*/ | ||
1946 | if (ah->ah_version != AR5K_AR5210) | ||
1947 | ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); | ||
1948 | } | ||
1949 | |||
1950 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) | ||
1951 | { | ||
1952 | ATH5K_TRACE(ah->ah_sc); | ||
1953 | /*Just a try M.F.*/ | ||
1954 | if (ah->ah_version != AR5K_AR5210) | ||
1955 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | ||
1956 | |||
1957 | return false; /*XXX: What do we return for 5210 ?*/ | ||
1958 | } | ||
1959 | |||
1960 | /* | ||
1961 | * TX power setup | ||
1962 | */ | ||
1963 | |||
1964 | /* | ||
1965 | * Initialize the tx power table (not fully implemented) | ||
1966 | */ | ||
1967 | static void ath5k_txpower_table(struct ath5k_hw *ah, | ||
1968 | struct ieee80211_channel *channel, s16 max_power) | ||
1969 | { | ||
1970 | unsigned int i, min, max, n; | ||
1971 | u16 txpower, *rates; | ||
1972 | |||
1973 | rates = ah->ah_txpower.txp_rates; | ||
1974 | |||
1975 | txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2; | ||
1976 | if (max_power > txpower) | ||
1977 | txpower = max_power > AR5K_TUNE_MAX_TXPOWER ? | ||
1978 | AR5K_TUNE_MAX_TXPOWER : max_power; | ||
1979 | |||
1980 | for (i = 0; i < AR5K_MAX_RATES; i++) | ||
1981 | rates[i] = txpower; | ||
1982 | |||
1983 | /* XXX setup target powers by rate */ | ||
1984 | |||
1985 | ah->ah_txpower.txp_min = rates[7]; | ||
1986 | ah->ah_txpower.txp_max = rates[0]; | ||
1987 | ah->ah_txpower.txp_ofdm = rates[0]; | ||
1988 | |||
1989 | /* Calculate the power table */ | ||
1990 | n = ARRAY_SIZE(ah->ah_txpower.txp_pcdac); | ||
1991 | min = AR5K_EEPROM_PCDAC_START; | ||
1992 | max = AR5K_EEPROM_PCDAC_STOP; | ||
1993 | for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP) | ||
1994 | ah->ah_txpower.txp_pcdac[i] = | ||
1995 | #ifdef notyet | ||
1996 | min + ((i * (max - min)) / n); | ||
1997 | #else | ||
1998 | min; | ||
1999 | #endif | ||
2000 | } | ||
2001 | |||
2002 | /* | ||
2003 | * Set transmition power | ||
2004 | */ | ||
2005 | int /*O.K. - txpower_table is unimplemented so this doesn't work*/ | ||
2006 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
2007 | unsigned int txpower) | ||
2008 | { | ||
2009 | bool tpc = ah->ah_txpower.txp_tpc; | ||
2010 | unsigned int i; | ||
2011 | |||
2012 | ATH5K_TRACE(ah->ah_sc); | ||
2013 | if (txpower > AR5K_TUNE_MAX_TXPOWER) { | ||
2014 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); | ||
2015 | return -EINVAL; | ||
2016 | } | ||
2017 | |||
2018 | /* Reset TX power values */ | ||
2019 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | ||
2020 | ah->ah_txpower.txp_tpc = tpc; | ||
2021 | |||
2022 | /* Initialize TX power table */ | ||
2023 | ath5k_txpower_table(ah, channel, txpower); | ||
2024 | |||
2025 | /* | ||
2026 | * Write TX power values | ||
2027 | */ | ||
2028 | for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { | ||
2029 | ath5k_hw_reg_write(ah, | ||
2030 | ((((ah->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & 0xffff) << 16) | | ||
2031 | (((ah->ah_txpower.txp_pcdac[(i << 1) ] << 8) | 0xff) & 0xffff), | ||
2032 | AR5K_PHY_PCDAC_TXPOWER(i)); | ||
2033 | } | ||
2034 | |||
2035 | ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) | | ||
2036 | AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) | | ||
2037 | AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1); | ||
2038 | |||
2039 | ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) | | ||
2040 | AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) | | ||
2041 | AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2); | ||
2042 | |||
2043 | ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) | | ||
2044 | AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) | | ||
2045 | AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3); | ||
2046 | |||
2047 | ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) | | ||
2048 | AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | | ||
2049 | AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); | ||
2050 | |||
2051 | if (ah->ah_txpower.txp_tpc == true) | ||
2052 | ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | | ||
2053 | AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); | ||
2054 | else | ||
2055 | ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX | | ||
2056 | AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); | ||
2057 | |||
2058 | return 0; | ||
2059 | } | ||
2060 | |||
2061 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power) | ||
2062 | { | ||
2063 | /*Just a try M.F.*/ | ||
2064 | struct ieee80211_channel *channel = &ah->ah_current_channel; | ||
2065 | |||
2066 | ATH5K_TRACE(ah->ah_sc); | ||
2067 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, | ||
2068 | "changing txpower to %d\n", power); | ||
2069 | |||
2070 | return ath5k_hw_txpower(ah, channel, power); | ||
2071 | } | ||
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h new file mode 100644 index 000000000000..2f41c8398602 --- /dev/null +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -0,0 +1,1987 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com> | ||
3 | * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org> | ||
4 | * Copyright (c) 2007 Michael Taylor <mike.taylor@apprion.com> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k | ||
22 | * maintained by Reyk Floeter | ||
23 | * | ||
24 | * I tried to document those registers by looking at ar5k code, some | ||
25 | * 802.11 (802.11e mostly) papers and by reading various public available | ||
26 | * Atheros presentations and papers like these: | ||
27 | * | ||
28 | * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf | ||
29 | * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf | ||
30 | * | ||
31 | * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf | ||
32 | */ | ||
33 | |||
34 | |||
35 | |||
36 | /*====MAC DMA REGISTERS====*/ | ||
37 | |||
38 | /* | ||
39 | * AR5210-Specific TXDP registers | ||
40 | * 5210 has only 2 transmit queues so no DCU/QCU, just | ||
41 | * 2 transmit descriptor pointers... | ||
42 | */ | ||
43 | #define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */ | ||
44 | #define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */ | ||
45 | |||
46 | /* | ||
47 | * Mac Control Register | ||
48 | */ | ||
49 | #define AR5K_CR 0x0008 /* Register Address */ | ||
50 | #define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */ | ||
51 | #define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */ | ||
52 | #define AR5K_CR_RXE 0x00000004 /* RX Enable */ | ||
53 | #define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */ | ||
54 | #define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */ | ||
55 | #define AR5K_CR_RXD 0x00000020 /* RX Disable */ | ||
56 | #define AR5K_CR_SWI 0x00000040 | ||
57 | |||
58 | /* | ||
59 | * RX Descriptor Pointer register | ||
60 | */ | ||
61 | #define AR5K_RXDP 0x000c | ||
62 | |||
63 | /* | ||
64 | * Configuration and status register | ||
65 | */ | ||
66 | #define AR5K_CFG 0x0014 /* Register Address */ | ||
67 | #define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */ | ||
68 | #define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer (?) */ | ||
69 | #define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ | ||
70 | #define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer (?) */ | ||
71 | #define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register values (?) */ | ||
72 | #define AR5K_CFG_ADHOC 0x00000020 /* [5211+] */ | ||
73 | #define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ | ||
74 | #define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ | ||
75 | #define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (?) */ | ||
76 | #define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */ | ||
77 | #define AR5K_CFG_TXCNT_S 11 | ||
78 | #define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */ | ||
79 | #define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */ | ||
80 | #define AR5K_CFG_PCI_THRES 0x00060000 /* [5211+] */ | ||
81 | #define AR5K_CFG_PCI_THRES_S 17 | ||
82 | |||
83 | /* | ||
84 | * Interrupt enable register | ||
85 | */ | ||
86 | #define AR5K_IER 0x0024 /* Register Address */ | ||
87 | #define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */ | ||
88 | #define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */ | ||
89 | |||
90 | |||
91 | /* | ||
92 | * 0x0028 is Beacon Control Register on 5210 | ||
93 | * and first RTS duration register on 5211 | ||
94 | */ | ||
95 | |||
96 | /* | ||
97 | * Beacon control register [5210] | ||
98 | */ | ||
99 | #define AR5K_BCR 0x0028 /* Register Address */ | ||
100 | #define AR5K_BCR_AP 0x00000000 /* AP mode */ | ||
101 | #define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */ | ||
102 | #define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */ | ||
103 | #define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */ | ||
104 | #define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */ | ||
105 | #define AR5K_BCR_BCGET 0x00000010 | ||
106 | |||
107 | /* | ||
108 | * First RTS duration register [5211] | ||
109 | */ | ||
110 | #define AR5K_RTSD0 0x0028 /* Register Address */ | ||
111 | #define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */ | ||
112 | #define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */ | ||
113 | #define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/ | ||
114 | #define AR5K_RTSD0_9_S 8 | ||
115 | #define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/ | ||
116 | #define AR5K_RTSD0_12_S 16 | ||
117 | #define AR5K_RTSD0_18 0xff000000 /* 16Mb*/ | ||
118 | #define AR5K_RTSD0_18_S 24 | ||
119 | |||
120 | |||
121 | /* | ||
122 | * 0x002c is Beacon Status Register on 5210 | ||
123 | * and second RTS duration register on 5211 | ||
124 | */ | ||
125 | |||
126 | /* | ||
127 | * Beacon status register [5210] | ||
128 | * | ||
129 | * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR | ||
130 | * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning | ||
131 | * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). | ||
132 | * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i | ||
133 | * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what | ||
134 | * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. | ||
135 | */ | ||
136 | #define AR5K_BSR 0x002c /* Register Address */ | ||
137 | #define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */ | ||
138 | #define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */ | ||
139 | #define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */ | ||
140 | #define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */ | ||
141 | #define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */ | ||
142 | #define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */ | ||
143 | #define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */ | ||
144 | #define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */ | ||
145 | #define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */ | ||
146 | #define AR5K_BSR_SWBA_CNT 0x00ff0000 | ||
147 | |||
148 | /* | ||
149 | * Second RTS duration register [5211] | ||
150 | */ | ||
151 | #define AR5K_RTSD1 0x002c /* Register Address */ | ||
152 | #define AR5K_RTSD1_24 0x000000ff /* 24Mb */ | ||
153 | #define AR5K_RTSD1_24_S 0 | ||
154 | #define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */ | ||
155 | #define AR5K_RTSD1_36_S 8 | ||
156 | #define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */ | ||
157 | #define AR5K_RTSD1_48_S 16 | ||
158 | #define AR5K_RTSD1_54 0xff000000 /* 54Mb */ | ||
159 | #define AR5K_RTSD1_54_S 24 | ||
160 | |||
161 | |||
162 | /* | ||
163 | * Transmit configuration register | ||
164 | */ | ||
165 | #define AR5K_TXCFG 0x0030 /* Register Address */ | ||
166 | #define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size */ | ||
167 | #define AR5K_TXCFG_SDMAMR_S 0 | ||
168 | #define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ | ||
169 | #define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ | ||
170 | #define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ | ||
171 | #define AR5K_TXCFG_TXFULL_S 4 | ||
172 | #define AR5K_TXCFG_TXFULL_0B 0x00000000 | ||
173 | #define AR5K_TXCFG_TXFULL_64B 0x00000010 | ||
174 | #define AR5K_TXCFG_TXFULL_128B 0x00000020 | ||
175 | #define AR5K_TXCFG_TXFULL_192B 0x00000030 | ||
176 | #define AR5K_TXCFG_TXFULL_256B 0x00000040 | ||
177 | #define AR5K_TXCFG_TXCONT_EN 0x00000080 | ||
178 | #define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ | ||
179 | #define AR5K_TXCFG_JUMBO_TXE 0x00000400 /* Enable jumbo frames transmition (?) [5211+] */ | ||
180 | #define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ | ||
181 | #define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ | ||
182 | #define AR5K_TXCFG_RDY_DIS 0x00004000 /* [5211+] */ | ||
183 | |||
184 | /* | ||
185 | * Receive configuration register | ||
186 | */ | ||
187 | #define AR5K_RXCFG 0x0034 /* Register Address */ | ||
188 | #define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size */ | ||
189 | #define AR5K_RXCFG_SDMAMW_S 0 | ||
190 | #define AR5K_RXCFG_DEF_ANTENNA 0x00000008 /* Default antenna */ | ||
191 | #define AR5K_RXCFG_ZLFDMA 0x00000010 /* Zero-length DMA */ | ||
192 | #define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo frames reception (?) [5211+] */ | ||
193 | #define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames (?) [5211+] */ | ||
194 | |||
195 | /* | ||
196 | * Receive jumbo descriptor last address register | ||
197 | * Only found in 5211 (?) | ||
198 | */ | ||
199 | #define AR5K_RXJLA 0x0038 | ||
200 | |||
201 | /* | ||
202 | * MIB control register | ||
203 | */ | ||
204 | #define AR5K_MIBC 0x0040 /* Register Address */ | ||
205 | #define AR5K_MIBC_COW 0x00000001 | ||
206 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze Mib Counters (?) */ | ||
207 | #define AR5K_MIBC_CMC 0x00000004 /* Clean Mib Counters (?) */ | ||
208 | #define AR5K_MIBC_MCS 0x00000008 | ||
209 | |||
210 | /* | ||
211 | * Timeout prescale register | ||
212 | */ | ||
213 | #define AR5K_TOPS 0x0044 | ||
214 | #define AR5K_TOPS_M 0x0000ffff /* [5211+] (?) */ | ||
215 | |||
216 | /* | ||
217 | * Receive timeout register (no frame received) | ||
218 | */ | ||
219 | #define AR5K_RXNOFRM 0x0048 | ||
220 | #define AR5K_RXNOFRM_M 0x000003ff /* [5211+] (?) */ | ||
221 | |||
222 | /* | ||
223 | * Transmit timeout register (no frame sent) | ||
224 | */ | ||
225 | #define AR5K_TXNOFRM 0x004c | ||
226 | #define AR5K_TXNOFRM_M 0x000003ff /* [5211+] (?) */ | ||
227 | #define AR5K_TXNOFRM_QCU 0x000ffc00 /* [5211+] (?) */ | ||
228 | |||
229 | /* | ||
230 | * Receive frame gap timeout register | ||
231 | */ | ||
232 | #define AR5K_RPGTO 0x0050 | ||
233 | #define AR5K_RPGTO_M 0x000003ff /* [5211+] (?) */ | ||
234 | |||
235 | /* | ||
236 | * Receive frame count limit register | ||
237 | */ | ||
238 | #define AR5K_RFCNT 0x0054 | ||
239 | #define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */ | ||
240 | #define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */ | ||
241 | |||
242 | /* | ||
243 | * Misc settings register | ||
244 | */ | ||
245 | #define AR5K_MISC 0x0058 /* Register Address */ | ||
246 | #define AR5K_MISC_DMA_OBS_M 0x000001e0 | ||
247 | #define AR5K_MISC_DMA_OBS_S 5 | ||
248 | #define AR5K_MISC_MISC_OBS_M 0x00000e00 | ||
249 | #define AR5K_MISC_MISC_OBS_S 9 | ||
250 | #define AR5K_MISC_MAC_OBS_LSB_M 0x00007000 | ||
251 | #define AR5K_MISC_MAC_OBS_LSB_S 12 | ||
252 | #define AR5K_MISC_MAC_OBS_MSB_M 0x00038000 | ||
253 | #define AR5K_MISC_MAC_OBS_MSB_S 15 | ||
254 | #define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */ | ||
255 | #define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */ | ||
256 | |||
257 | /* | ||
258 | * QCU/DCU clock gating register (5311) | ||
259 | */ | ||
260 | #define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */ | ||
261 | #define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */ | ||
262 | #define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */ | ||
263 | |||
264 | /* | ||
265 | * Interrupt Status Registers | ||
266 | * | ||
267 | * For 5210 there is only one status register but for | ||
268 | * 5211/5212 we have one primary and 4 secondary registers. | ||
269 | * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. | ||
270 | * Most of these bits are common for all chipsets. | ||
271 | */ | ||
272 | #define AR5K_ISR 0x001c /* Register Address [5210] */ | ||
273 | #define AR5K_PISR 0x0080 /* Register Address [5211+] */ | ||
274 | #define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ | ||
275 | #define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ | ||
276 | #define AR5K_ISR_RXERR 0x00000004 /* Receive error */ | ||
277 | #define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ | ||
278 | #define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */ | ||
279 | #define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */ | ||
280 | #define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */ | ||
281 | #define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ | ||
282 | #define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ | ||
283 | #define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */ | ||
284 | #define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ | ||
285 | #define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ | ||
286 | #define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ | ||
287 | #define AR5K_ISR_SWI 0x00002000 /* Software interrupt (?) */ | ||
288 | #define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ | ||
289 | #define AR5K_ISR_RXKCM 0x00008000 | ||
290 | #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ | ||
291 | #define AR5K_ISR_BRSSI 0x00020000 | ||
292 | #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ | ||
293 | #define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ | ||
294 | #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ | ||
295 | #define AR5K_ISR_MCABT 0x00100000 /* [5210] */ | ||
296 | #define AR5K_ISR_RXCHIRP 0x00200000 /* [5212+] */ | ||
297 | #define AR5K_ISR_SSERR 0x00200000 /* [5210] */ | ||
298 | #define AR5K_ISR_DPERR 0x00400000 /* [5210] */ | ||
299 | #define AR5K_ISR_TIM 0x00800000 /* [5210] */ | ||
300 | #define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */ | ||
301 | #define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/ | ||
302 | #define AR5K_ISR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */ | ||
303 | #define AR5K_ISR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */ | ||
304 | #define AR5K_ISR_QTRIG 0x08000000 /* [5211+] */ | ||
305 | |||
306 | /* | ||
307 | * Secondary status registers [5211+] (0 - 4) | ||
308 | * | ||
309 | * I guess from the names that these give the status for each | ||
310 | * queue, that's why only masks are defined here, haven't got | ||
311 | * any info about them (couldn't find them anywhere in ar5k code). | ||
312 | */ | ||
313 | #define AR5K_SISR0 0x0084 /* Register Address [5211+] */ | ||
314 | #define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ | ||
315 | #define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ | ||
316 | |||
317 | #define AR5K_SISR1 0x0088 /* Register Address [5211+] */ | ||
318 | #define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ | ||
319 | #define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ | ||
320 | |||
321 | #define AR5K_SISR2 0x008c /* Register Address [5211+] */ | ||
322 | #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ | ||
323 | #define AR5K_SISR2_MCABT 0x00100000 | ||
324 | #define AR5K_SISR2_SSERR 0x00200000 | ||
325 | #define AR5K_SISR2_DPERR 0x00400000 | ||
326 | #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ | ||
327 | #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ | ||
328 | #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* [5212+] */ | ||
329 | #define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* [5212+] */ | ||
330 | #define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* [5212+] */ | ||
331 | #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ | ||
332 | |||
333 | #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ | ||
334 | #define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ | ||
335 | #define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ | ||
336 | |||
337 | #define AR5K_SISR4 0x0094 /* Register Address [5211+] */ | ||
338 | #define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */ | ||
339 | |||
340 | /* | ||
341 | * Shadow read-and-clear interrupt status registers [5211+] | ||
342 | */ | ||
343 | #define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */ | ||
344 | #define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */ | ||
345 | #define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */ | ||
346 | #define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */ | ||
347 | #define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */ | ||
348 | #define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */ | ||
349 | |||
350 | /* | ||
351 | * Interrupt Mask Registers | ||
352 | * | ||
353 | * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary | ||
354 | * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. | ||
355 | */ | ||
356 | #define AR5K_IMR 0x0020 /* Register Address [5210] */ | ||
357 | #define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ | ||
358 | #define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ | ||
359 | #define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ | ||
360 | #define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ | ||
361 | #define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ | ||
362 | #define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/ | ||
363 | #define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/ | ||
364 | #define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/ | ||
365 | #define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/ | ||
366 | #define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/ | ||
367 | #define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/ | ||
368 | #define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/ | ||
369 | #define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/ | ||
370 | #define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/ | ||
371 | #define AR5K_IMR_SWI 0x00002000 | ||
372 | #define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ | ||
373 | #define AR5K_IMR_RXKCM 0x00008000 | ||
374 | #define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ | ||
375 | #define AR5K_IMR_BRSSI 0x00020000 | ||
376 | #define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ | ||
377 | #define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ | ||
378 | #define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ | ||
379 | #define AR5K_IMR_MCABT 0x00100000 /* [5210] */ | ||
380 | #define AR5K_IMR_RXCHIRP 0x00200000 /* [5212+]*/ | ||
381 | #define AR5K_IMR_SSERR 0x00200000 /* [5210] */ | ||
382 | #define AR5K_IMR_DPERR 0x00400000 /* [5210] */ | ||
383 | #define AR5K_IMR_TIM 0x00800000 /* [5211+] */ | ||
384 | #define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */ | ||
385 | #define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ | ||
386 | #define AR5K_IMR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */ | ||
387 | #define AR5K_IMR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */ | ||
388 | #define AR5K_IMR_QTRIG 0x08000000 /* [5211+] */ | ||
389 | |||
390 | /* | ||
391 | * Secondary interrupt mask registers [5211+] (0 - 4) | ||
392 | */ | ||
393 | #define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */ | ||
394 | #define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ | ||
395 | #define AR5K_SIMR0_QCU_TXOK_S 0 | ||
396 | #define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ | ||
397 | #define AR5K_SIMR0_QCU_TXDESC_S 16 | ||
398 | |||
399 | #define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */ | ||
400 | #define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ | ||
401 | #define AR5K_SIMR1_QCU_TXERR_S 0 | ||
402 | #define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ | ||
403 | #define AR5K_SIMR1_QCU_TXEOL_S 16 | ||
404 | |||
405 | #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ | ||
406 | #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ | ||
407 | #define AR5K_SIMR2_QCU_TXURN_S 0 | ||
408 | #define AR5K_SIMR2_MCABT 0x00100000 | ||
409 | #define AR5K_SIMR2_SSERR 0x00200000 | ||
410 | #define AR5K_SIMR2_DPERR 0x00400000 | ||
411 | #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ | ||
412 | #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ | ||
413 | #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* [5212+] */ | ||
414 | #define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* [5212+] */ | ||
415 | #define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* [5212+] */ | ||
416 | #define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ | ||
417 | |||
418 | #define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ | ||
419 | #define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ | ||
420 | #define AR5K_SIMR3_QCBRORN_S 0 | ||
421 | #define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ | ||
422 | #define AR5K_SIMR3_QCBRURN_S 16 | ||
423 | |||
424 | #define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */ | ||
425 | #define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */ | ||
426 | #define AR5K_SIMR4_QTRIG_S 0 | ||
427 | |||
428 | |||
429 | /* | ||
430 | * Decompression mask registers [5212+] | ||
431 | */ | ||
432 | #define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (?)*/ | ||
433 | #define AR5K_DCM_DATA 0x0404 /*Decompression mask data (?)*/ | ||
434 | |||
435 | /* | ||
436 | * Decompression configuration registers [5212+] | ||
437 | */ | ||
438 | #define AR5K_DCCFG 0x0420 | ||
439 | |||
440 | /* | ||
441 | * Compression configuration registers [5212+] | ||
442 | */ | ||
443 | #define AR5K_CCFG 0x0600 | ||
444 | #define AR5K_CCFG_CUP 0x0604 | ||
445 | |||
446 | /* | ||
447 | * Compression performance counter registers [5212+] | ||
448 | */ | ||
449 | #define AR5K_CPC0 0x0610 /* Compression performance counter 0 */ | ||
450 | #define AR5K_CPC1 0x0614 /* Compression performance counter 1*/ | ||
451 | #define AR5K_CPC2 0x0618 /* Compression performance counter 2 */ | ||
452 | #define AR5K_CPC3 0x061c /* Compression performance counter 3 */ | ||
453 | #define AR5K_CPCORN 0x0620 /* Compression performance overrun (?) */ | ||
454 | |||
455 | |||
456 | /* | ||
457 | * Queue control unit (QCU) registers [5211+] | ||
458 | * | ||
459 | * Card has 12 TX Queues but i see that only 0-9 are used (?) | ||
460 | * both in binary HAL (see ah.h) and ar5k. Each queue has it's own | ||
461 | * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate) | ||
462 | * configuration register (0x08c0 - 0x08ec), a ready time configuration | ||
463 | * register (0x0900 - 0x092c), a misc configuration register (0x09c0 - | ||
464 | * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some | ||
465 | * global registers, QCU transmit enable/disable and "one shot arm (?)" | ||
466 | * set/clear, which contain status for all queues (we shift by 1 for each | ||
467 | * queue). To access these registers easily we define some macros here | ||
468 | * that are used inside HAL. For more infos check out *_tx_queue functs. | ||
469 | * | ||
470 | * TODO: Boundary checking on macros (here?) | ||
471 | */ | ||
472 | |||
473 | /* | ||
474 | * Generic QCU Register access macros | ||
475 | */ | ||
476 | #define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r) | ||
477 | #define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q)) | ||
478 | #define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q)) | ||
479 | |||
480 | /* | ||
481 | * QCU Transmit descriptor pointer registers | ||
482 | */ | ||
483 | #define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */ | ||
484 | #define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q) | ||
485 | |||
486 | /* | ||
487 | * QCU Transmit enable register | ||
488 | */ | ||
489 | #define AR5K_QCU_TXE 0x0840 | ||
490 | #define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q) | ||
491 | #define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q) | ||
492 | |||
493 | /* | ||
494 | * QCU Transmit disable register | ||
495 | */ | ||
496 | #define AR5K_QCU_TXD 0x0880 | ||
497 | #define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q) | ||
498 | #define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q) | ||
499 | |||
500 | /* | ||
501 | * QCU Constant Bit Rate configuration registers | ||
502 | */ | ||
503 | #define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */ | ||
504 | #define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */ | ||
505 | #define AR5K_QCU_CBRCFG_INTVAL_S 0 | ||
506 | #define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */ | ||
507 | #define AR5K_QCU_CBRCFG_ORN_THRES_S 24 | ||
508 | #define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q) | ||
509 | |||
510 | /* | ||
511 | * QCU Ready time configuration registers | ||
512 | */ | ||
513 | #define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */ | ||
514 | #define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */ | ||
515 | #define AR5K_QCU_RDYTIMECFG_INTVAL_S 0 | ||
516 | #define AR5K_QCU_RDYTIMECFG_DURATION 0x00ffffff /* Ready time duration mask */ | ||
517 | #define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */ | ||
518 | #define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q) | ||
519 | |||
520 | /* | ||
521 | * QCU one shot arm set registers | ||
522 | */ | ||
523 | #define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */ | ||
524 | #define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff | ||
525 | |||
526 | /* | ||
527 | * QCU one shot arm clear registers | ||
528 | */ | ||
529 | #define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */ | ||
530 | #define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff | ||
531 | |||
532 | /* | ||
533 | * QCU misc registers | ||
534 | */ | ||
535 | #define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */ | ||
536 | #define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ | ||
537 | #define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ | ||
538 | #define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ | ||
539 | #define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */ | ||
540 | #define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */ | ||
541 | #define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */ | ||
542 | #define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ | ||
543 | #define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */ | ||
544 | #define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */ | ||
545 | #define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Beacons enabled */ | ||
546 | #define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled (?) */ | ||
547 | #define AR5K_QCU_MISC_TXE 0x00000200 /* TXE reset when RDYTIME enalbed (?) */ | ||
548 | #define AR5K_QCU_MISC_CBR 0x00000400 /* CBR threshold reset (?) */ | ||
549 | #define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU reset (?) */ | ||
550 | #define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q) | ||
551 | |||
552 | |||
553 | /* | ||
554 | * QCU status registers | ||
555 | */ | ||
556 | #define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */ | ||
557 | #define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */ | ||
558 | #define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter (?) */ | ||
559 | #define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q) | ||
560 | |||
561 | /* | ||
562 | * QCU ready time shutdown register | ||
563 | */ | ||
564 | #define AR5K_QCU_RDYTIMESHDN 0x0a40 | ||
565 | #define AR5K_QCU_RDYTIMESHDN_M 0x000003ff | ||
566 | |||
567 | /* | ||
568 | * QCU compression buffer base registers [5212+] | ||
569 | */ | ||
570 | #define AR5K_QCU_CBB_SELECT 0x0b00 | ||
571 | #define AR5K_QCU_CBB_ADDR 0x0b04 | ||
572 | |||
573 | /* | ||
574 | * QCU compression buffer configuration register [5212+] | ||
575 | */ | ||
576 | #define AR5K_QCU_CBCFG 0x0b08 | ||
577 | |||
578 | |||
579 | |||
580 | /* | ||
581 | * Distributed Coordination Function (DCF) control unit (DCU) | ||
582 | * registers [5211+] | ||
583 | * | ||
584 | * These registers control the various characteristics of each queue | ||
585 | * for 802.11e (WME) combatibility so they go together with | ||
586 | * QCU registers in pairs. For each queue we have a QCU mask register, | ||
587 | * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c), | ||
588 | * a retry limit register (0x1080 - 0x10ac), a channel time register | ||
589 | * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and | ||
590 | * a sequence number register (0x1140 - 0x116c). It seems that "global" | ||
591 | * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k). | ||
592 | * We use the same macros here for easier register access. | ||
593 | * | ||
594 | */ | ||
595 | |||
596 | /* | ||
597 | * DCU QCU mask registers | ||
598 | */ | ||
599 | #define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */ | ||
600 | #define AR5K_DCU_QCUMASK_M 0x000003ff | ||
601 | #define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q) | ||
602 | |||
603 | /* | ||
604 | * DCU local Inter Frame Space settings register | ||
605 | */ | ||
606 | #define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */ | ||
607 | #define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */ | ||
608 | #define AR5K_DCU_LCL_IFS_CW_MIN_S 0 | ||
609 | #define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */ | ||
610 | #define AR5K_DCU_LCL_IFS_CW_MAX_S 10 | ||
611 | #define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */ | ||
612 | #define AR5K_DCU_LCL_IFS_AIFS_S 20 | ||
613 | #define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q) | ||
614 | |||
615 | /* | ||
616 | * DCU retry limit registers | ||
617 | */ | ||
618 | #define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ | ||
619 | #define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ | ||
620 | #define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 | ||
621 | #define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ | ||
622 | #define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 | ||
623 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ | ||
624 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 | ||
625 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ | ||
626 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 | ||
627 | #define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) | ||
628 | |||
629 | /* | ||
630 | * DCU channel time registers | ||
631 | */ | ||
632 | #define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */ | ||
633 | #define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */ | ||
634 | #define AR5K_DCU_CHAN_TIME_DUR_S 0 | ||
635 | #define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */ | ||
636 | #define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q) | ||
637 | |||
638 | /* | ||
639 | * DCU misc registers [5211+] | ||
640 | * | ||
641 | * For some of the registers i couldn't find in the code | ||
642 | * (only backoff stuff is there realy) i tried to match the | ||
643 | * names with 802.11e parameters etc, so i guess VIRTCOL here | ||
644 | * means Virtual Collision and HCFPOLL means Hybrid Coordination | ||
645 | * factor Poll (CF- Poll). Arbiter lockout control controls the | ||
646 | * behaviour on low priority queues when we have multiple queues | ||
647 | * with pending frames. Intra-frame lockout means we wait until | ||
648 | * the queue's current frame transmits (with post frame backoff and bursting) | ||
649 | * before we transmit anything else and global lockout means we | ||
650 | * wait for the whole queue to finish before higher priority queues | ||
651 | * can transmit (this is used on beacon and CAB queues). | ||
652 | * No lockout means there is no special handling. | ||
653 | */ | ||
654 | #define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ | ||
655 | #define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff setting (?) */ | ||
656 | #define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ | ||
657 | #define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll (?) */ | ||
658 | #define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff (?) */ | ||
659 | #define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch (?) */ | ||
660 | #define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ | ||
661 | #define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 | ||
662 | #define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1 | ||
663 | #define AR5K_DCU_MISC_VIRTCOL_IGNORE 2 | ||
664 | #define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Beacon enable (?) */ | ||
665 | #define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ | ||
666 | #define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 | ||
667 | #define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ | ||
668 | #define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */ | ||
669 | #define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */ | ||
670 | #define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 | ||
671 | #define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment (?) */ | ||
672 | #define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff (?) */ | ||
673 | #define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision policy (?) */ | ||
674 | #define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 | ||
675 | #define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */ | ||
676 | #define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q) | ||
677 | |||
678 | /* | ||
679 | * DCU frame sequence number registers | ||
680 | */ | ||
681 | #define AR5K_DCU_SEQNUM_BASE 0x1140 | ||
682 | #define AR5K_DCU_SEQNUM_M 0x00000fff | ||
683 | #define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q) | ||
684 | |||
685 | /* | ||
686 | * DCU global IFS SIFS registers | ||
687 | */ | ||
688 | #define AR5K_DCU_GBL_IFS_SIFS 0x1030 | ||
689 | #define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff | ||
690 | |||
691 | /* | ||
692 | * DCU global IFS slot interval registers | ||
693 | */ | ||
694 | #define AR5K_DCU_GBL_IFS_SLOT 0x1070 | ||
695 | #define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff | ||
696 | |||
697 | /* | ||
698 | * DCU global IFS EIFS registers | ||
699 | */ | ||
700 | #define AR5K_DCU_GBL_IFS_EIFS 0x10b0 | ||
701 | #define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff | ||
702 | |||
703 | /* | ||
704 | * DCU global IFS misc registers | ||
705 | */ | ||
706 | #define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */ | ||
707 | #define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 | ||
708 | #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode (?) */ | ||
709 | #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask (?) */ | ||
710 | #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 | ||
711 | #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 | ||
712 | |||
713 | /* | ||
714 | * DCU frame prefetch control register | ||
715 | */ | ||
716 | #define AR5K_DCU_FP 0x1230 | ||
717 | |||
718 | /* | ||
719 | * DCU transmit pause control/status register | ||
720 | */ | ||
721 | #define AR5K_DCU_TXP 0x1270 /* Register Address */ | ||
722 | #define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask (?) */ | ||
723 | #define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status (?) */ | ||
724 | |||
725 | /* | ||
726 | * DCU transmit filter register | ||
727 | */ | ||
728 | #define AR5K_DCU_TX_FILTER 0x1038 | ||
729 | |||
730 | /* | ||
731 | * DCU clear transmit filter register | ||
732 | */ | ||
733 | #define AR5K_DCU_TX_FILTER_CLR 0x143c | ||
734 | |||
735 | /* | ||
736 | * DCU set transmit filter register | ||
737 | */ | ||
738 | #define AR5K_DCU_TX_FILTER_SET 0x147c | ||
739 | |||
740 | /* | ||
741 | * Reset control register | ||
742 | * | ||
743 | * 4 and 8 are not used in 5211/5212 and | ||
744 | * 2 means "baseband reset" on 5211/5212. | ||
745 | */ | ||
746 | #define AR5K_RESET_CTL 0x4000 /* Register Address */ | ||
747 | #define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ | ||
748 | #define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */ | ||
749 | #define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */ | ||
750 | #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ | ||
751 | #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ | ||
752 | #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ | ||
753 | #define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \ | ||
754 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY) | ||
755 | |||
756 | /* | ||
757 | * Sleep control register | ||
758 | */ | ||
759 | #define AR5K_SLEEP_CTL 0x4004 /* Register Address */ | ||
760 | #define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */ | ||
761 | #define AR5K_SLEEP_CTL_SLDUR_S 0 | ||
762 | #define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */ | ||
763 | #define AR5K_SLEEP_CTL_SLE_S 16 | ||
764 | #define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */ | ||
765 | #define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ | ||
766 | #define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 | ||
767 | #define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ | ||
768 | |||
769 | /* | ||
770 | * Interrupt pending register | ||
771 | */ | ||
772 | #define AR5K_INTPEND 0x4008 | ||
773 | #define AR5K_INTPEND_M 0x00000001 | ||
774 | |||
775 | /* | ||
776 | * Sleep force register | ||
777 | */ | ||
778 | #define AR5K_SFR 0x400c | ||
779 | #define AR5K_SFR_M 0x00000001 | ||
780 | |||
781 | /* | ||
782 | * PCI configuration register | ||
783 | */ | ||
784 | #define AR5K_PCICFG 0x4010 /* Register Address */ | ||
785 | #define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ | ||
786 | #define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ | ||
787 | #define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ | ||
788 | #define AR5K_PCICFG_EESIZE_S 3 | ||
789 | #define AR5K_PCICFG_EESIZE_4K 0 /* 4K */ | ||
790 | #define AR5K_PCICFG_EESIZE_8K 1 /* 8K */ | ||
791 | #define AR5K_PCICFG_EESIZE_16K 2 /* 16K */ | ||
792 | #define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */ | ||
793 | #define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */ | ||
794 | #define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */ | ||
795 | #define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */ | ||
796 | #define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */ | ||
797 | #define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */ | ||
798 | #define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */ | ||
799 | #define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */ | ||
800 | #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ | ||
801 | #define AR5K_PCICFG_SL_INPEN 0x00002800 /* Sleep even whith pending interrupts (?) */ | ||
802 | #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ | ||
803 | #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ | ||
804 | #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ | ||
805 | #define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */ | ||
806 | #define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */ | ||
807 | #define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */ | ||
808 | #define AR5K_PCICFG_LEDBLINK 0x00700000 | ||
809 | #define AR5K_PCICFG_LEDBLINK_S 20 | ||
810 | #define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slow led blink rate (?) [5211+] */ | ||
811 | #define AR5K_PCICFG_LEDSTATE \ | ||
812 | (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ | ||
813 | AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) | ||
814 | |||
815 | /* | ||
816 | * "General Purpose Input/Output" (GPIO) control register | ||
817 | * | ||
818 | * I'm not sure about this but after looking at the code | ||
819 | * for all chipsets here is what i got. | ||
820 | * | ||
821 | * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits) | ||
822 | * Mode 0 -> always input | ||
823 | * Mode 1 -> output when GPIODO for this GPIO is set to 0 | ||
824 | * Mode 2 -> output when GPIODO for this GPIO is set to 1 | ||
825 | * Mode 3 -> always output | ||
826 | * | ||
827 | * For more infos check out get_gpio/set_gpio and | ||
828 | * set_gpio_input/set_gpio_output functs. | ||
829 | * For more infos on gpio interrupt check out set_gpio_intr. | ||
830 | */ | ||
831 | #define AR5K_NUM_GPIO 6 | ||
832 | |||
833 | #define AR5K_GPIOCR 0x4014 /* Register Address */ | ||
834 | #define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ | ||
835 | #define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is off (?) */ | ||
836 | #define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is on */ | ||
837 | #define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */ | ||
838 | #define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */ | ||
839 | #define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */ | ||
840 | #define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */ | ||
841 | #define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */ | ||
842 | |||
843 | /* | ||
844 | * "General Purpose Input/Output" (GPIO) data output register | ||
845 | */ | ||
846 | #define AR5K_GPIODO 0x4018 | ||
847 | |||
848 | /* | ||
849 | * "General Purpose Input/Output" (GPIO) data input register | ||
850 | */ | ||
851 | #define AR5K_GPIODI 0x401c | ||
852 | #define AR5K_GPIODI_M 0x0000002f | ||
853 | |||
854 | |||
855 | /* | ||
856 | * Silicon revision register | ||
857 | */ | ||
858 | #define AR5K_SREV 0x4020 /* Register Address */ | ||
859 | #define AR5K_SREV_REV 0x0000000f /* Mask for revision */ | ||
860 | #define AR5K_SREV_REV_S 0 | ||
861 | #define AR5K_SREV_VER 0x000000ff /* Mask for version */ | ||
862 | #define AR5K_SREV_VER_S 4 | ||
863 | |||
864 | |||
865 | |||
866 | /*====EEPROM REGISTERS====*/ | ||
867 | |||
868 | /* | ||
869 | * EEPROM access registers | ||
870 | * | ||
871 | * Here we got a difference between 5210/5211-12 | ||
872 | * read data register for 5210 is at 0x6800 and | ||
873 | * status register is at 0x6c00. There is also | ||
874 | * no eeprom command register on 5210 and the | ||
875 | * offsets are different. | ||
876 | * | ||
877 | * To read eeprom data for a specific offset: | ||
878 | * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) | ||
879 | * read AR5K_EEPROM_BASE +(4 * offset) | ||
880 | * check the eeprom status register | ||
881 | * and read eeprom data register. | ||
882 | * | ||
883 | * 5211 - write offset to AR5K_EEPROM_BASE | ||
884 | * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD | ||
885 | * check the eeprom status register | ||
886 | * and read eeprom data register. | ||
887 | * | ||
888 | * To write eeprom data for a specific offset: | ||
889 | * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) | ||
890 | * write data to AR5K_EEPROM_BASE +(4 * offset) | ||
891 | * check the eeprom status register | ||
892 | * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD | ||
893 | * 5212 write offset to AR5K_EEPROM_BASE | ||
894 | * write data to data register | ||
895 | * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD | ||
896 | * check the eeprom status register | ||
897 | * | ||
898 | * For more infos check eeprom_* functs and the ar5k.c | ||
899 | * file posted in madwifi-devel mailing list. | ||
900 | * http://sourceforge.net/mailarchive/message.php?msg_id=8966525 | ||
901 | * | ||
902 | */ | ||
903 | #define AR5K_EEPROM_BASE 0x6000 | ||
904 | |||
905 | /* | ||
906 | * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) | ||
907 | */ | ||
908 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ | ||
909 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ | ||
910 | #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ | ||
911 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | ||
912 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | ||
913 | |||
914 | #define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ | ||
915 | #define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ | ||
916 | #define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ | ||
917 | #define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ | ||
918 | #define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 | ||
919 | #define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ | ||
920 | #define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 | ||
921 | #define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ | ||
922 | #define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 | ||
923 | #define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ | ||
924 | #define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 | ||
925 | #define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ | ||
926 | #define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 | ||
927 | #define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ | ||
928 | #define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 | ||
929 | #define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ | ||
930 | #define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 | ||
931 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | ||
932 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | ||
933 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | ||
934 | #define AR5K_EEPROM_INFO_CKSUM 0xffff | ||
935 | #define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) | ||
936 | |||
937 | #define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ | ||
938 | #define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ | ||
939 | #define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ | ||
940 | #define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ | ||
941 | #define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ | ||
942 | #define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */ | ||
943 | #define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ | ||
944 | #define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ | ||
945 | #define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ | ||
946 | #define AR5K_EEPROM_VERSION_4_3 0x4003 | ||
947 | #define AR5K_EEPROM_VERSION_4_4 0x4004 | ||
948 | #define AR5K_EEPROM_VERSION_4_5 0x4005 | ||
949 | #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ | ||
950 | #define AR5K_EEPROM_VERSION_4_7 0x3007 | ||
951 | |||
952 | #define AR5K_EEPROM_MODE_11A 0 | ||
953 | #define AR5K_EEPROM_MODE_11B 1 | ||
954 | #define AR5K_EEPROM_MODE_11G 2 | ||
955 | |||
956 | #define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ | ||
957 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) | ||
958 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) | ||
959 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) | ||
960 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | ||
961 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | ||
962 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | ||
963 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */ | ||
964 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | ||
965 | |||
966 | #define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c | ||
967 | #define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 | ||
968 | #define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 | ||
969 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 | ||
970 | |||
971 | /* Newer EEPROMs are using a different offset */ | ||
972 | #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ | ||
973 | (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) | ||
974 | |||
975 | #define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) | ||
976 | #define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff)) | ||
977 | #define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff)) | ||
978 | |||
979 | /* calibration settings */ | ||
980 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | ||
981 | #define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) | ||
982 | #define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) | ||
983 | #define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ | ||
984 | |||
985 | /* [3.1 - 3.3] */ | ||
986 | #define AR5K_EEPROM_OBDB0_2GHZ 0x00ec | ||
987 | #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed | ||
988 | |||
989 | /* Misc values available since EEPROM 4.0 */ | ||
990 | #define AR5K_EEPROM_MISC0 0x00c4 | ||
991 | #define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) | ||
992 | #define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) | ||
993 | #define AR5K_EEPROM_MISC1 0x00c5 | ||
994 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | ||
995 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | ||
996 | |||
997 | /* | ||
998 | * EEPROM data register | ||
999 | */ | ||
1000 | #define AR5K_EEPROM_DATA_5211 0x6004 | ||
1001 | #define AR5K_EEPROM_DATA_5210 0x6800 | ||
1002 | #define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \ | ||
1003 | AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211) | ||
1004 | |||
1005 | /* | ||
1006 | * EEPROM command register | ||
1007 | */ | ||
1008 | #define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ | ||
1009 | #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ | ||
1010 | #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ | ||
1011 | #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ | ||
1012 | |||
1013 | /* | ||
1014 | * EEPROM status register | ||
1015 | */ | ||
1016 | #define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ | ||
1017 | #define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ | ||
1018 | #define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \ | ||
1019 | AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211) | ||
1020 | #define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */ | ||
1021 | #define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */ | ||
1022 | #define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */ | ||
1023 | #define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ | ||
1024 | |||
1025 | /* | ||
1026 | * EEPROM config register (?) | ||
1027 | */ | ||
1028 | #define AR5K_EEPROM_CFG 0x6010 | ||
1029 | |||
1030 | |||
1031 | |||
1032 | /* | ||
1033 | * Protocol Control Unit (PCU) registers | ||
1034 | */ | ||
1035 | /* | ||
1036 | * Used for checking initial register writes | ||
1037 | * during channel reset (see reset func) | ||
1038 | */ | ||
1039 | #define AR5K_PCU_MIN 0x8000 | ||
1040 | #define AR5K_PCU_MAX 0x8fff | ||
1041 | |||
1042 | /* | ||
1043 | * First station id register (MAC address in lower 32 bits) | ||
1044 | */ | ||
1045 | #define AR5K_STA_ID0 0x8000 | ||
1046 | |||
1047 | /* | ||
1048 | * Second station id register (MAC address in upper 16 bits) | ||
1049 | */ | ||
1050 | #define AR5K_STA_ID1 0x8004 /* Register Address */ | ||
1051 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ | ||
1052 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ | ||
1053 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting (?) */ | ||
1054 | #define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */ | ||
1055 | #define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */ | ||
1056 | #define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */ | ||
1057 | #define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/ | ||
1058 | #define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \ | ||
1059 | AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211) | ||
1060 | #define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ | ||
1061 | #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ | ||
1062 | #define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS (?) */ | ||
1063 | #define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS (?) */ | ||
1064 | #define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */ | ||
1065 | |||
1066 | /* | ||
1067 | * First BSSID register (MAC address, lower 32bits) | ||
1068 | */ | ||
1069 | #define AR5K_BSS_ID0 0x8008 | ||
1070 | |||
1071 | /* | ||
1072 | * Second BSSID register (MAC address in upper 16 bits) | ||
1073 | * | ||
1074 | * AID: Association ID | ||
1075 | */ | ||
1076 | #define AR5K_BSS_ID1 0x800c | ||
1077 | #define AR5K_BSS_ID1_AID 0xffff0000 | ||
1078 | #define AR5K_BSS_ID1_AID_S 16 | ||
1079 | |||
1080 | /* | ||
1081 | * Backoff slot time register | ||
1082 | */ | ||
1083 | #define AR5K_SLOT_TIME 0x8010 | ||
1084 | |||
1085 | /* | ||
1086 | * ACK/CTS timeout register | ||
1087 | */ | ||
1088 | #define AR5K_TIME_OUT 0x8014 /* Register Address */ | ||
1089 | #define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */ | ||
1090 | #define AR5K_TIME_OUT_ACK_S 0 | ||
1091 | #define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */ | ||
1092 | #define AR5K_TIME_OUT_CTS_S 16 | ||
1093 | |||
1094 | /* | ||
1095 | * RSSI threshold register | ||
1096 | */ | ||
1097 | #define AR5K_RSSI_THR 0x8018 /* Register Address */ | ||
1098 | #define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */ | ||
1099 | #define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */ | ||
1100 | #define AR5K_RSSI_THR_BMISS_5210_S 8 | ||
1101 | #define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */ | ||
1102 | #define AR5K_RSSI_THR_BMISS_5211_S 8 | ||
1103 | #define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \ | ||
1104 | AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211) | ||
1105 | #define AR5K_RSSI_THR_BMISS_S 8 | ||
1106 | |||
1107 | /* | ||
1108 | * 5210 has more PCU registers because there is no QCU/DCU | ||
1109 | * so queue parameters are set here, this way a lot common | ||
1110 | * registers have different address for 5210. To make things | ||
1111 | * easier we define a macro based on ah->ah_version for common | ||
1112 | * registers with different addresses and common flags. | ||
1113 | */ | ||
1114 | |||
1115 | /* | ||
1116 | * Retry limit register | ||
1117 | * | ||
1118 | * Retry limit register for 5210 (no QCU/DCU so it's done in PCU) | ||
1119 | */ | ||
1120 | #define AR5K_NODCU_RETRY_LMT 0x801c /*Register Address */ | ||
1121 | #define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ | ||
1122 | #define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0 | ||
1123 | #define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */ | ||
1124 | #define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4 | ||
1125 | #define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */ | ||
1126 | #define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8 | ||
1127 | #define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */ | ||
1128 | #define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14 | ||
1129 | #define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */ | ||
1130 | #define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20 | ||
1131 | |||
1132 | /* | ||
1133 | * Transmit latency register | ||
1134 | */ | ||
1135 | #define AR5K_USEC_5210 0x8020 /* Register Address [5210] */ | ||
1136 | #define AR5K_USEC_5211 0x801c /* Register Address [5211+] */ | ||
1137 | #define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \ | ||
1138 | AR5K_USEC_5210 : AR5K_USEC_5211) | ||
1139 | #define AR5K_USEC_1 0x0000007f | ||
1140 | #define AR5K_USEC_1_S 0 | ||
1141 | #define AR5K_USEC_32 0x00003f80 | ||
1142 | #define AR5K_USEC_32_S 7 | ||
1143 | #define AR5K_USEC_TX_LATENCY_5211 0x007fc000 | ||
1144 | #define AR5K_USEC_TX_LATENCY_5211_S 14 | ||
1145 | #define AR5K_USEC_RX_LATENCY_5211 0x1f800000 | ||
1146 | #define AR5K_USEC_RX_LATENCY_5211_S 23 | ||
1147 | #define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */ | ||
1148 | #define AR5K_USEC_TX_LATENCY_5210_S 14 | ||
1149 | #define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */ | ||
1150 | #define AR5K_USEC_RX_LATENCY_5210_S 20 | ||
1151 | |||
1152 | /* | ||
1153 | * PCU beacon control register | ||
1154 | */ | ||
1155 | #define AR5K_BEACON_5210 0x8024 | ||
1156 | #define AR5K_BEACON_5211 0x8020 | ||
1157 | #define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \ | ||
1158 | AR5K_BEACON_5210 : AR5K_BEACON_5211) | ||
1159 | #define AR5K_BEACON_PERIOD 0x0000ffff | ||
1160 | #define AR5K_BEACON_PERIOD_S 0 | ||
1161 | #define AR5K_BEACON_TIM 0x007f0000 | ||
1162 | #define AR5K_BEACON_TIM_S 16 | ||
1163 | #define AR5K_BEACON_ENABLE 0x00800000 | ||
1164 | #define AR5K_BEACON_RESET_TSF 0x01000000 | ||
1165 | |||
1166 | /* | ||
1167 | * CFP period register | ||
1168 | */ | ||
1169 | #define AR5K_CFP_PERIOD_5210 0x8028 | ||
1170 | #define AR5K_CFP_PERIOD_5211 0x8024 | ||
1171 | #define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \ | ||
1172 | AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211) | ||
1173 | |||
1174 | /* | ||
1175 | * Next beacon time register | ||
1176 | */ | ||
1177 | #define AR5K_TIMER0_5210 0x802c | ||
1178 | #define AR5K_TIMER0_5211 0x8028 | ||
1179 | #define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \ | ||
1180 | AR5K_TIMER0_5210 : AR5K_TIMER0_5211) | ||
1181 | |||
1182 | /* | ||
1183 | * Next DMA beacon alert register | ||
1184 | */ | ||
1185 | #define AR5K_TIMER1_5210 0x8030 | ||
1186 | #define AR5K_TIMER1_5211 0x802c | ||
1187 | #define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \ | ||
1188 | AR5K_TIMER1_5210 : AR5K_TIMER1_5211) | ||
1189 | |||
1190 | /* | ||
1191 | * Next software beacon alert register | ||
1192 | */ | ||
1193 | #define AR5K_TIMER2_5210 0x8034 | ||
1194 | #define AR5K_TIMER2_5211 0x8030 | ||
1195 | #define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \ | ||
1196 | AR5K_TIMER2_5210 : AR5K_TIMER2_5211) | ||
1197 | |||
1198 | /* | ||
1199 | * Next ATIM window time register | ||
1200 | */ | ||
1201 | #define AR5K_TIMER3_5210 0x8038 | ||
1202 | #define AR5K_TIMER3_5211 0x8034 | ||
1203 | #define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \ | ||
1204 | AR5K_TIMER3_5210 : AR5K_TIMER3_5211) | ||
1205 | |||
1206 | |||
1207 | /* | ||
1208 | * 5210 First inter frame spacing register (IFS) | ||
1209 | */ | ||
1210 | #define AR5K_IFS0 0x8040 | ||
1211 | #define AR5K_IFS0_SIFS 0x000007ff | ||
1212 | #define AR5K_IFS0_SIFS_S 0 | ||
1213 | #define AR5K_IFS0_DIFS 0x007ff800 | ||
1214 | #define AR5K_IFS0_DIFS_S 11 | ||
1215 | |||
1216 | /* | ||
1217 | * 5210 Second inter frame spacing register (IFS) | ||
1218 | */ | ||
1219 | #define AR5K_IFS1 0x8044 | ||
1220 | #define AR5K_IFS1_PIFS 0x00000fff | ||
1221 | #define AR5K_IFS1_PIFS_S 0 | ||
1222 | #define AR5K_IFS1_EIFS 0x03fff000 | ||
1223 | #define AR5K_IFS1_EIFS_S 12 | ||
1224 | #define AR5K_IFS1_CS_EN 0x04000000 | ||
1225 | |||
1226 | |||
1227 | /* | ||
1228 | * CFP duration register | ||
1229 | */ | ||
1230 | #define AR5K_CFP_DUR_5210 0x8048 | ||
1231 | #define AR5K_CFP_DUR_5211 0x8038 | ||
1232 | #define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \ | ||
1233 | AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211) | ||
1234 | |||
1235 | /* | ||
1236 | * Receive filter register | ||
1237 | * TODO: Get these out of ar5xxx.h on ath5k | ||
1238 | */ | ||
1239 | #define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */ | ||
1240 | #define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */ | ||
1241 | #define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \ | ||
1242 | AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211) | ||
1243 | #define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */ | ||
1244 | #define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */ | ||
1245 | #define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */ | ||
1246 | #define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */ | ||
1247 | #define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */ | ||
1248 | #define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */ | ||
1249 | #define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */ | ||
1250 | #define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */ | ||
1251 | #define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */ | ||
1252 | #define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */ | ||
1253 | #define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */ | ||
1254 | #define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */ | ||
1255 | #define AR5K_RX_FILTER_PHYERR \ | ||
1256 | ((ah->ah_version == AR5K_AR5211 ? \ | ||
1257 | AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212)) | ||
1258 | #define AR5K_RX_FILTER_RADARERR \ | ||
1259 | ((ah->ah_version == AR5K_AR5211 ? \ | ||
1260 | AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212)) | ||
1261 | |||
1262 | /* | ||
1263 | * Multicast filter register (lower 32 bits) | ||
1264 | */ | ||
1265 | #define AR5K_MCAST_FILTER0_5210 0x8050 | ||
1266 | #define AR5K_MCAST_FILTER0_5211 0x8040 | ||
1267 | #define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \ | ||
1268 | AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211) | ||
1269 | |||
1270 | /* | ||
1271 | * Multicast filter register (higher 16 bits) | ||
1272 | */ | ||
1273 | #define AR5K_MCAST_FILTER1_5210 0x8054 | ||
1274 | #define AR5K_MCAST_FILTER1_5211 0x8044 | ||
1275 | #define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \ | ||
1276 | AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211) | ||
1277 | |||
1278 | |||
1279 | /* | ||
1280 | * Transmit mask register (lower 32 bits) [5210] | ||
1281 | */ | ||
1282 | #define AR5K_TX_MASK0 0x8058 | ||
1283 | |||
1284 | /* | ||
1285 | * Transmit mask register (higher 16 bits) [5210] | ||
1286 | */ | ||
1287 | #define AR5K_TX_MASK1 0x805c | ||
1288 | |||
1289 | /* | ||
1290 | * Clear transmit mask [5210] | ||
1291 | */ | ||
1292 | #define AR5K_CLR_TMASK 0x8060 | ||
1293 | |||
1294 | /* | ||
1295 | * Trigger level register (before transmission) [5210] | ||
1296 | */ | ||
1297 | #define AR5K_TRIG_LVL 0x8064 | ||
1298 | |||
1299 | |||
1300 | /* | ||
1301 | * PCU control register | ||
1302 | * | ||
1303 | * Only DIS_RX is used in the code, the rest i guess are | ||
1304 | * for tweaking/diagnostics. | ||
1305 | */ | ||
1306 | #define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ | ||
1307 | #define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ | ||
1308 | #define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \ | ||
1309 | AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211) | ||
1310 | #define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 | ||
1311 | #define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs (?) */ | ||
1312 | #define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs (?) */ | ||
1313 | #define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption (?) */ | ||
1314 | #define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption (?) */ | ||
1315 | #define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ | ||
1316 | #define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ | ||
1317 | #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 | ||
1318 | #define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ | ||
1319 | AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) | ||
1320 | #define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ | ||
1321 | #define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 | ||
1322 | #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ | ||
1323 | AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) | ||
1324 | #define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 | ||
1325 | #define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 | ||
1326 | #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ | ||
1327 | AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) | ||
1328 | #define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 | ||
1329 | #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 | ||
1330 | #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ | ||
1331 | AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) | ||
1332 | #define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Scrambler seed (?) */ | ||
1333 | #define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 | ||
1334 | #define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ | ||
1335 | AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) | ||
1336 | #define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ | ||
1337 | #define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ | ||
1338 | #define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask (?) */ | ||
1339 | #define AR5K_DIAG_SW_SCRAM_SEED_S 10 | ||
1340 | #define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ | ||
1341 | #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 | ||
1342 | #define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 | ||
1343 | #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ | ||
1344 | AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) | ||
1345 | #define AR5K_DIAG_SW_OBSPT_M 0x000c0000 | ||
1346 | #define AR5K_DIAG_SW_OBSPT_S 18 | ||
1347 | |||
1348 | /* | ||
1349 | * TSF (clock) register (lower 32 bits) | ||
1350 | */ | ||
1351 | #define AR5K_TSF_L32_5210 0x806c | ||
1352 | #define AR5K_TSF_L32_5211 0x804c | ||
1353 | #define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \ | ||
1354 | AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211) | ||
1355 | |||
1356 | /* | ||
1357 | * TSF (clock) register (higher 32 bits) | ||
1358 | */ | ||
1359 | #define AR5K_TSF_U32_5210 0x8070 | ||
1360 | #define AR5K_TSF_U32_5211 0x8050 | ||
1361 | #define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \ | ||
1362 | AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211) | ||
1363 | |||
1364 | /* | ||
1365 | * Last beacon timestamp register | ||
1366 | */ | ||
1367 | #define AR5K_LAST_TSTP 0x8080 | ||
1368 | |||
1369 | /* | ||
1370 | * ADDAC test register [5211+] | ||
1371 | */ | ||
1372 | #define AR5K_ADDAC_TEST 0x8054 | ||
1373 | #define AR5K_ADDAC_TEST_TXCONT 0x00000001 | ||
1374 | |||
1375 | /* | ||
1376 | * Default antenna register [5211+] | ||
1377 | */ | ||
1378 | #define AR5K_DEFAULT_ANTENNA 0x8058 | ||
1379 | |||
1380 | |||
1381 | |||
1382 | /* | ||
1383 | * Retry count register [5210] | ||
1384 | */ | ||
1385 | #define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */ | ||
1386 | #define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */ | ||
1387 | #define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */ | ||
1388 | |||
1389 | /* | ||
1390 | * Back-off status register [5210] | ||
1391 | */ | ||
1392 | #define AR5K_BACKOFF 0x8088 /* Register Address [5210] */ | ||
1393 | #define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */ | ||
1394 | #define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */ | ||
1395 | |||
1396 | |||
1397 | |||
1398 | /* | ||
1399 | * NAV register (current) | ||
1400 | */ | ||
1401 | #define AR5K_NAV_5210 0x808c | ||
1402 | #define AR5K_NAV_5211 0x8084 | ||
1403 | #define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \ | ||
1404 | AR5K_NAV_5210 : AR5K_NAV_5211) | ||
1405 | |||
1406 | /* | ||
1407 | * RTS success register | ||
1408 | */ | ||
1409 | #define AR5K_RTS_OK_5210 0x8090 | ||
1410 | #define AR5K_RTS_OK_5211 0x8088 | ||
1411 | #define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \ | ||
1412 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) | ||
1413 | |||
1414 | /* | ||
1415 | * RTS failure register | ||
1416 | */ | ||
1417 | #define AR5K_RTS_FAIL_5210 0x8094 | ||
1418 | #define AR5K_RTS_FAIL_5211 0x808c | ||
1419 | #define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \ | ||
1420 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) | ||
1421 | |||
1422 | /* | ||
1423 | * ACK failure register | ||
1424 | */ | ||
1425 | #define AR5K_ACK_FAIL_5210 0x8098 | ||
1426 | #define AR5K_ACK_FAIL_5211 0x8090 | ||
1427 | #define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \ | ||
1428 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) | ||
1429 | |||
1430 | /* | ||
1431 | * FCS failure register | ||
1432 | */ | ||
1433 | #define AR5K_FCS_FAIL_5210 0x809c | ||
1434 | #define AR5K_FCS_FAIL_5211 0x8094 | ||
1435 | #define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \ | ||
1436 | AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211) | ||
1437 | |||
1438 | /* | ||
1439 | * Beacon count register | ||
1440 | */ | ||
1441 | #define AR5K_BEACON_CNT_5210 0x80a0 | ||
1442 | #define AR5K_BEACON_CNT_5211 0x8098 | ||
1443 | #define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \ | ||
1444 | AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211) | ||
1445 | |||
1446 | |||
1447 | /*===5212 Specific PCU registers===*/ | ||
1448 | |||
1449 | /* | ||
1450 | * XR (eXtended Range) mode register | ||
1451 | */ | ||
1452 | #define AR5K_XRMODE 0x80c0 | ||
1453 | #define AR5K_XRMODE_POLL_TYPE_M 0x0000003f | ||
1454 | #define AR5K_XRMODE_POLL_TYPE_S 0 | ||
1455 | #define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c | ||
1456 | #define AR5K_XRMODE_POLL_SUBTYPE_S 2 | ||
1457 | #define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 | ||
1458 | #define AR5K_XRMODE_SIFS_DELAY 0x000fff00 | ||
1459 | #define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 | ||
1460 | #define AR5K_XRMODE_FRAME_HOLD_S 20 | ||
1461 | |||
1462 | /* | ||
1463 | * XR delay register | ||
1464 | */ | ||
1465 | #define AR5K_XRDELAY 0x80c4 | ||
1466 | #define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff | ||
1467 | #define AR5K_XRDELAY_SLOT_DELAY_S 0 | ||
1468 | #define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 | ||
1469 | #define AR5K_XRDELAY_CHIRP_DELAY_S 16 | ||
1470 | |||
1471 | /* | ||
1472 | * XR timeout register | ||
1473 | */ | ||
1474 | #define AR5K_XRTIMEOUT 0x80c8 | ||
1475 | #define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff | ||
1476 | #define AR5K_XRTIMEOUT_CHIRP_S 0 | ||
1477 | #define AR5K_XRTIMEOUT_POLL_M 0xffff0000 | ||
1478 | #define AR5K_XRTIMEOUT_POLL_S 16 | ||
1479 | |||
1480 | /* | ||
1481 | * XR chirp register | ||
1482 | */ | ||
1483 | #define AR5K_XRCHIRP 0x80cc | ||
1484 | #define AR5K_XRCHIRP_SEND 0x00000001 | ||
1485 | #define AR5K_XRCHIRP_GAP 0xffff0000 | ||
1486 | |||
1487 | /* | ||
1488 | * XR stomp register | ||
1489 | */ | ||
1490 | #define AR5K_XRSTOMP 0x80d0 | ||
1491 | #define AR5K_XRSTOMP_TX 0x00000001 | ||
1492 | #define AR5K_XRSTOMP_RX_ABORT 0x00000002 | ||
1493 | #define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 | ||
1494 | |||
1495 | /* | ||
1496 | * First enhanced sleep register | ||
1497 | */ | ||
1498 | #define AR5K_SLEEP0 0x80d4 | ||
1499 | #define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff | ||
1500 | #define AR5K_SLEEP0_NEXT_DTIM_S 0 | ||
1501 | #define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 | ||
1502 | #define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 | ||
1503 | #define AR5K_SLEEP0_CABTO 0xff000000 | ||
1504 | #define AR5K_SLEEP0_CABTO_S 24 | ||
1505 | |||
1506 | /* | ||
1507 | * Second enhanced sleep register | ||
1508 | */ | ||
1509 | #define AR5K_SLEEP1 0x80d8 | ||
1510 | #define AR5K_SLEEP1_NEXT_TIM 0x0007ffff | ||
1511 | #define AR5K_SLEEP1_NEXT_TIM_S 0 | ||
1512 | #define AR5K_SLEEP1_BEACON_TO 0xff000000 | ||
1513 | #define AR5K_SLEEP1_BEACON_TO_S 24 | ||
1514 | |||
1515 | /* | ||
1516 | * Third enhanced sleep register | ||
1517 | */ | ||
1518 | #define AR5K_SLEEP2 0x80dc | ||
1519 | #define AR5K_SLEEP2_TIM_PER 0x0000ffff | ||
1520 | #define AR5K_SLEEP2_TIM_PER_S 0 | ||
1521 | #define AR5K_SLEEP2_DTIM_PER 0xffff0000 | ||
1522 | #define AR5K_SLEEP2_DTIM_PER_S 16 | ||
1523 | |||
1524 | /* | ||
1525 | * BSSID mask registers | ||
1526 | */ | ||
1527 | #define AR5K_BSS_IDM0 0x80e0 | ||
1528 | #define AR5K_BSS_IDM1 0x80e4 | ||
1529 | |||
1530 | /* | ||
1531 | * TX power control (TPC) register | ||
1532 | */ | ||
1533 | #define AR5K_TXPC 0x80e8 | ||
1534 | #define AR5K_TXPC_ACK_M 0x0000003f | ||
1535 | #define AR5K_TXPC_ACK_S 0 | ||
1536 | #define AR5K_TXPC_CTS_M 0x00003f00 | ||
1537 | #define AR5K_TXPC_CTS_S 8 | ||
1538 | #define AR5K_TXPC_CHIRP_M 0x003f0000 | ||
1539 | #define AR5K_TXPC_CHIRP_S 22 | ||
1540 | |||
1541 | /* | ||
1542 | * Profile count registers | ||
1543 | */ | ||
1544 | #define AR5K_PROFCNT_TX 0x80ec | ||
1545 | #define AR5K_PROFCNT_RX 0x80f0 | ||
1546 | #define AR5K_PROFCNT_RXCLR 0x80f4 | ||
1547 | #define AR5K_PROFCNT_CYCLE 0x80f8 | ||
1548 | |||
1549 | /* | ||
1550 | * TSF parameter register | ||
1551 | */ | ||
1552 | #define AR5K_TSF_PARM 0x8104 | ||
1553 | #define AR5K_TSF_PARM_INC_M 0x000000ff | ||
1554 | #define AR5K_TSF_PARM_INC_S 0 | ||
1555 | |||
1556 | /* | ||
1557 | * PHY error filter register | ||
1558 | */ | ||
1559 | #define AR5K_PHY_ERR_FIL 0x810c | ||
1560 | #define AR5K_PHY_ERR_FIL_RADAR 0x00000020 | ||
1561 | #define AR5K_PHY_ERR_FIL_OFDM 0x00020000 | ||
1562 | #define AR5K_PHY_ERR_FIL_CCK 0x02000000 | ||
1563 | |||
1564 | /* | ||
1565 | * Rate duration register | ||
1566 | */ | ||
1567 | #define AR5K_RATE_DUR_BASE 0x8700 | ||
1568 | #define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2)) | ||
1569 | |||
1570 | /*===5212 end===*/ | ||
1571 | |||
1572 | /* | ||
1573 | * Key table (WEP) register | ||
1574 | */ | ||
1575 | #define AR5K_KEYTABLE_0_5210 0x9000 | ||
1576 | #define AR5K_KEYTABLE_0_5211 0x8800 | ||
1577 | #define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) | ||
1578 | #define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) | ||
1579 | #define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ | ||
1580 | AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) | ||
1581 | #define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) | ||
1582 | #define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) | ||
1583 | #define AR5K_KEYTABLE_TYPE_40 0x00000000 | ||
1584 | #define AR5K_KEYTABLE_TYPE_104 0x00000001 | ||
1585 | #define AR5K_KEYTABLE_TYPE_128 0x00000003 | ||
1586 | #define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ | ||
1587 | #define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ | ||
1588 | #define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ | ||
1589 | #define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ | ||
1590 | #define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ | ||
1591 | #define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) | ||
1592 | #define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) | ||
1593 | #define AR5K_KEYTABLE_VALID 0x00008000 | ||
1594 | |||
1595 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit | ||
1596 | * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit | ||
1597 | * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit | ||
1598 | * | ||
1599 | * Some vendors have introduced bigger WEP keys to address | ||
1600 | * security vulnerabilities in WEP. This includes: | ||
1601 | * | ||
1602 | * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit | ||
1603 | * | ||
1604 | * We can expand this if we find ar5k Atheros cards with a larger | ||
1605 | * key table size. | ||
1606 | */ | ||
1607 | #define AR5K_KEYTABLE_SIZE_5210 64 | ||
1608 | #define AR5K_KEYTABLE_SIZE_5211 128 | ||
1609 | #define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ | ||
1610 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) | ||
1611 | |||
1612 | |||
1613 | /*===PHY REGISTERS===*/ | ||
1614 | |||
1615 | /* | ||
1616 | * PHY register | ||
1617 | */ | ||
1618 | #define AR5K_PHY_BASE 0x9800 | ||
1619 | #define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) | ||
1620 | #define AR5K_PHY_SHIFT_2GHZ 0x00004007 | ||
1621 | #define AR5K_PHY_SHIFT_5GHZ 0x00000007 | ||
1622 | |||
1623 | /* | ||
1624 | * PHY frame control register [5110] /turbo mode register [5111+] | ||
1625 | * | ||
1626 | * There is another frame control register for [5111+] | ||
1627 | * at address 0x9944 (see below) but the 2 first flags | ||
1628 | * are common here between 5110 frame control register | ||
1629 | * and [5111+] turbo mode register, so this also works as | ||
1630 | * a "turbo mode register" for 5110. We treat this one as | ||
1631 | * a frame control register for 5110 below. | ||
1632 | */ | ||
1633 | #define AR5K_PHY_TURBO 0x9804 | ||
1634 | #define AR5K_PHY_TURBO_MODE 0x00000001 | ||
1635 | #define AR5K_PHY_TURBO_SHORT 0x00000002 | ||
1636 | |||
1637 | /* | ||
1638 | * PHY agility command register | ||
1639 | */ | ||
1640 | #define AR5K_PHY_AGC 0x9808 | ||
1641 | #define AR5K_PHY_AGC_DISABLE 0x08000000 | ||
1642 | |||
1643 | /* | ||
1644 | * PHY timing register [5112+] | ||
1645 | */ | ||
1646 | #define AR5K_PHY_TIMING_3 0x9814 | ||
1647 | #define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000 | ||
1648 | #define AR5K_PHY_TIMING_3_DSC_MAN_S 17 | ||
1649 | #define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000 | ||
1650 | #define AR5K_PHY_TIMING_3_DSC_EXP_S 13 | ||
1651 | |||
1652 | /* | ||
1653 | * PHY chip revision register | ||
1654 | */ | ||
1655 | #define AR5K_PHY_CHIP_ID 0x9818 | ||
1656 | |||
1657 | /* | ||
1658 | * PHY activation register | ||
1659 | */ | ||
1660 | #define AR5K_PHY_ACT 0x981c | ||
1661 | #define AR5K_PHY_ACT_ENABLE 0x00000001 | ||
1662 | #define AR5K_PHY_ACT_DISABLE 0x00000002 | ||
1663 | |||
1664 | /* | ||
1665 | * PHY signal register | ||
1666 | */ | ||
1667 | #define AR5K_PHY_SIG 0x9858 | ||
1668 | #define AR5K_PHY_SIG_FIRSTEP 0x0003f000 | ||
1669 | #define AR5K_PHY_SIG_FIRSTEP_S 12 | ||
1670 | #define AR5K_PHY_SIG_FIRPWR 0x03fc0000 | ||
1671 | #define AR5K_PHY_SIG_FIRPWR_S 18 | ||
1672 | |||
1673 | /* | ||
1674 | * PHY coarse agility control register | ||
1675 | */ | ||
1676 | #define AR5K_PHY_AGCCOARSE 0x985c | ||
1677 | #define AR5K_PHY_AGCCOARSE_LO 0x00007f80 | ||
1678 | #define AR5K_PHY_AGCCOARSE_LO_S 7 | ||
1679 | #define AR5K_PHY_AGCCOARSE_HI 0x003f8000 | ||
1680 | #define AR5K_PHY_AGCCOARSE_HI_S 15 | ||
1681 | |||
1682 | /* | ||
1683 | * PHY agility control register | ||
1684 | */ | ||
1685 | #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ | ||
1686 | #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ | ||
1687 | #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ | ||
1688 | |||
1689 | /* | ||
1690 | * PHY noise floor status register | ||
1691 | */ | ||
1692 | #define AR5K_PHY_NF 0x9864 | ||
1693 | #define AR5K_PHY_NF_M 0x000001ff | ||
1694 | #define AR5K_PHY_NF_ACTIVE 0x00000100 | ||
1695 | #define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) | ||
1696 | #define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) | ||
1697 | #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) | ||
1698 | |||
1699 | /* | ||
1700 | * PHY ADC saturation register [5110] | ||
1701 | */ | ||
1702 | #define AR5K_PHY_ADCSAT 0x9868 | ||
1703 | #define AR5K_PHY_ADCSAT_ICNT 0x0001f800 | ||
1704 | #define AR5K_PHY_ADCSAT_ICNT_S 11 | ||
1705 | #define AR5K_PHY_ADCSAT_THR 0x000007e0 | ||
1706 | #define AR5K_PHY_ADCSAT_THR_S 5 | ||
1707 | |||
1708 | /* | ||
1709 | * PHY sleep registers [5112+] | ||
1710 | */ | ||
1711 | #define AR5K_PHY_SCR 0x9870 | ||
1712 | #define AR5K_PHY_SCR_32MHZ 0x0000001f | ||
1713 | #define AR5K_PHY_SLMT 0x9874 | ||
1714 | #define AR5K_PHY_SLMT_32MHZ 0x0000007f | ||
1715 | #define AR5K_PHY_SCAL 0x9878 | ||
1716 | #define AR5K_PHY_SCAL_32MHZ 0x0000000e | ||
1717 | |||
1718 | /* | ||
1719 | * PHY PLL (Phase Locked Loop) control register | ||
1720 | */ | ||
1721 | #define AR5K_PHY_PLL 0x987c | ||
1722 | #define AR5K_PHY_PLL_20MHZ 0x13 /* For half rate (?) [5111+] */ | ||
1723 | #define AR5K_PHY_PLL_40MHZ_5211 0x18 /* For 802.11a */ | ||
1724 | #define AR5K_PHY_PLL_40MHZ_5212 0x000000aa | ||
1725 | #define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \ | ||
1726 | AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212) | ||
1727 | #define AR5K_PHY_PLL_44MHZ_5211 0x19 /* For 802.11b/g */ | ||
1728 | #define AR5K_PHY_PLL_44MHZ_5212 0x000000ab | ||
1729 | #define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \ | ||
1730 | AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) | ||
1731 | #define AR5K_PHY_PLL_RF5111 0x00000000 | ||
1732 | #define AR5K_PHY_PLL_RF5112 0x00000040 | ||
1733 | |||
1734 | /* | ||
1735 | * RF Buffer register | ||
1736 | * | ||
1737 | * There are some special control registers on the RF chip | ||
1738 | * that hold various operation settings related mostly to | ||
1739 | * the analog parts (channel, gain adjustment etc). | ||
1740 | * | ||
1741 | * We don't write on those registers directly but | ||
1742 | * we send a data packet on the buffer register and | ||
1743 | * then write on another special register to notify hw | ||
1744 | * to apply the settings. This is done so that control registers | ||
1745 | * can be dynamicaly programmed during operation and the settings | ||
1746 | * are applied faster on the hw. | ||
1747 | * | ||
1748 | * We sent such data packets during rf initialization and channel change | ||
1749 | * through ath5k_hw_rf*_rfregs and ath5k_hw_rf*_channel functions. | ||
1750 | * | ||
1751 | * The data packets we send during initializadion are inside ath5k_ini_rf | ||
1752 | * struct (see ath5k_hw.h) and each one is related to an "rf register bank". | ||
1753 | * We use *rfregs functions to modify them acording to current operation | ||
1754 | * mode and eeprom values and pass them all together to the chip. | ||
1755 | * | ||
1756 | * It's obvious from the code that 0x989c is the buffer register but | ||
1757 | * for the other special registers that we write to after sending each | ||
1758 | * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers | ||
1759 | * for now. It's interesting that they are also used for some other operations. | ||
1760 | * | ||
1761 | * Also check out hw.h and U.S. Patent 6677779 B1 (about buffer | ||
1762 | * registers and control registers): | ||
1763 | * | ||
1764 | * http://www.google.com/patents?id=qNURAAAAEBAJ | ||
1765 | */ | ||
1766 | |||
1767 | #define AR5K_RF_BUFFER 0x989c | ||
1768 | #define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */ | ||
1769 | #define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */ | ||
1770 | #define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */ | ||
1771 | |||
1772 | #define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */ | ||
1773 | /* Channel set on 5111 */ | ||
1774 | /* Used to read radio revision*/ | ||
1775 | |||
1776 | #define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */ | ||
1777 | /* Bank 0,1,2,6 on 5111 */ | ||
1778 | /* Bank 1 on 5112 */ | ||
1779 | /* Used during activation on 5111 */ | ||
1780 | |||
1781 | #define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */ | ||
1782 | /* Used during activation on 5111 */ | ||
1783 | /* Channel on 5112 */ | ||
1784 | /* Bank 6 on 5112 */ | ||
1785 | |||
1786 | #define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */ | ||
1787 | |||
1788 | /* | ||
1789 | * PHY RF stage register [5210] | ||
1790 | */ | ||
1791 | #define AR5K_PHY_RFSTG 0x98d4 | ||
1792 | #define AR5K_PHY_RFSTG_DISABLE 0x00000021 | ||
1793 | |||
1794 | /* | ||
1795 | * PHY receiver delay register [5111+] | ||
1796 | */ | ||
1797 | #define AR5K_PHY_RX_DELAY 0x9914 | ||
1798 | #define AR5K_PHY_RX_DELAY_M 0x00003fff | ||
1799 | |||
1800 | /* | ||
1801 | * PHY timing I(nphase) Q(adrature) control register [5111+] | ||
1802 | */ | ||
1803 | #define AR5K_PHY_IQ 0x9920 /* Register address */ | ||
1804 | #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ | ||
1805 | #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ | ||
1806 | #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 | ||
1807 | #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ | ||
1808 | #define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 | ||
1809 | #define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12 | ||
1810 | #define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */ | ||
1811 | |||
1812 | |||
1813 | /* | ||
1814 | * PHY PAPD probe register [5111+ (?)] | ||
1815 | * Is this only present in 5212 ? | ||
1816 | * Because it's always 0 in 5211 initialization code | ||
1817 | */ | ||
1818 | #define AR5K_PHY_PAPD_PROBE 0x9930 | ||
1819 | #define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00 | ||
1820 | #define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9 | ||
1821 | #define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000 | ||
1822 | #define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */ | ||
1823 | #define AR5K_PHY_PAPD_PROBE_TYPE_S 23 | ||
1824 | #define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0 | ||
1825 | #define AR5K_PHY_PAPD_PROBE_TYPE_XR 1 | ||
1826 | #define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2 | ||
1827 | #define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000 | ||
1828 | #define AR5K_PHY_PAPD_PROBE_GAINF_S 25 | ||
1829 | #define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */ | ||
1830 | #define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */ | ||
1831 | |||
1832 | |||
1833 | /* | ||
1834 | * PHY TX rate power registers [5112+] | ||
1835 | */ | ||
1836 | #define AR5K_PHY_TXPOWER_RATE1 0x9934 | ||
1837 | #define AR5K_PHY_TXPOWER_RATE2 0x9938 | ||
1838 | #define AR5K_PHY_TXPOWER_RATE_MAX 0x993c | ||
1839 | #define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040 | ||
1840 | #define AR5K_PHY_TXPOWER_RATE3 0xa234 | ||
1841 | #define AR5K_PHY_TXPOWER_RATE4 0xa238 | ||
1842 | |||
1843 | /* | ||
1844 | * PHY frame control register [5111+] | ||
1845 | */ | ||
1846 | #define AR5K_PHY_FRAME_CTL_5210 0x9804 | ||
1847 | #define AR5K_PHY_FRAME_CTL_5211 0x9944 | ||
1848 | #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ | ||
1849 | AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) | ||
1850 | /*---[5111+]---*/ | ||
1851 | #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 | ||
1852 | #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 | ||
1853 | /*---[5110/5111]---*/ | ||
1854 | #define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 | ||
1855 | #define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 | ||
1856 | #define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* illegal rate */ | ||
1857 | #define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* illegal length */ | ||
1858 | #define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000 | ||
1859 | #define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* tx underrun */ | ||
1860 | #define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ | ||
1861 | AR5K_PHY_FRAME_CTL_TXURN_ERR | \ | ||
1862 | AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ | ||
1863 | AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ | ||
1864 | AR5K_PHY_FRAME_CTL_PARITY_ERR | \ | ||
1865 | AR5K_PHY_FRAME_CTL_TIMING_ERR | ||
1866 | |||
1867 | /* | ||
1868 | * PHY radar detection register [5111+] | ||
1869 | */ | ||
1870 | #define AR5K_PHY_RADAR 0x9954 | ||
1871 | |||
1872 | /* Radar enable ........ ........ ........ .......1 */ | ||
1873 | #define AR5K_PHY_RADAR_ENABLE 0x00000001 | ||
1874 | #define AR5K_PHY_RADAR_DISABLE 0x00000000 | ||
1875 | #define AR5K_PHY_RADAR_ENABLE_S 0 | ||
1876 | |||
1877 | /* This is the value found on the card .1.111.1 .1.1.... 111....1 1...1... | ||
1878 | at power on. */ | ||
1879 | #define AR5K_PHY_RADAR_PWONDEF_AR5213 0x5d50e188 | ||
1880 | |||
1881 | /* This is the value found on the card .1.1.111 ..11...1 .1...1.1 1...11.1 | ||
1882 | after DFS is enabled */ | ||
1883 | #define AR5K_PHY_RADAR_ENABLED_AR5213 0x5731458d | ||
1884 | |||
1885 | /* Finite Impulse Response (FIR) filter .1111111 ........ ........ ........ | ||
1886 | * power out threshold. | ||
1887 | * 7-bits, standard power range {0..127} in 1/2 dBm units. */ | ||
1888 | #define AR5K_PHY_RADAR_FIRPWROUTTHR 0x7f000000 | ||
1889 | #define AR5K_PHY_RADAR_FIRPWROUTTHR_S 24 | ||
1890 | |||
1891 | /* Radar RSSI/SNR threshold. ........ 111111.. ........ ........ | ||
1892 | * 6-bits, dBm range {0..63} in dBm units. */ | ||
1893 | #define AR5K_PHY_RADAR_RADARRSSITHR 0x00fc0000 | ||
1894 | #define AR5K_PHY_RADAR_RADARRSSITHR_S 18 | ||
1895 | |||
1896 | /* Pulse height threshold ........ ......11 1111.... ........ | ||
1897 | * 6-bits, dBm range {0..63} in dBm units. */ | ||
1898 | #define AR5K_PHY_RADAR_PULSEHEIGHTTHR 0x0003f000 | ||
1899 | #define AR5K_PHY_RADAR_PULSEHEIGHTTHR_S 12 | ||
1900 | |||
1901 | /* Pulse RSSI/SNR threshold ........ ........ ....1111 11...... | ||
1902 | * 6-bits, dBm range {0..63} in dBm units. */ | ||
1903 | #define AR5K_PHY_RADAR_PULSERSSITHR 0x00000fc0 | ||
1904 | #define AR5K_PHY_RADAR_PULSERSSITHR_S 6 | ||
1905 | |||
1906 | /* Inband threshold ........ ........ ........ ..11111. | ||
1907 | * 5-bits, units unknown {0..31} (? MHz ?) */ | ||
1908 | #define AR5K_PHY_RADAR_INBANDTHR 0x0000003e | ||
1909 | #define AR5K_PHY_RADAR_INBANDTHR_S 1 | ||
1910 | |||
1911 | /* | ||
1912 | * PHY antenna switch table registers [5110] | ||
1913 | */ | ||
1914 | #define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 | ||
1915 | #define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 | ||
1916 | |||
1917 | /* | ||
1918 | * PHY clock sleep registers [5112+] | ||
1919 | */ | ||
1920 | #define AR5K_PHY_SCLOCK 0x99f0 | ||
1921 | #define AR5K_PHY_SCLOCK_32MHZ 0x0000000c | ||
1922 | #define AR5K_PHY_SDELAY 0x99f4 | ||
1923 | #define AR5K_PHY_SDELAY_32MHZ 0x000000ff | ||
1924 | #define AR5K_PHY_SPENDING 0x99f8 | ||
1925 | #define AR5K_PHY_SPENDING_RF5111 0x00000018 | ||
1926 | #define AR5K_PHY_SPENDING_RF5112 0x00000014 | ||
1927 | |||
1928 | /* | ||
1929 | * Misc PHY/radio registers [5110 - 5111] | ||
1930 | */ | ||
1931 | #define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ | ||
1932 | #define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) | ||
1933 | #define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ | ||
1934 | #define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2)) | ||
1935 | |||
1936 | /* | ||
1937 | * PHY timing IQ calibration result register [5111+] | ||
1938 | */ | ||
1939 | #define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ | ||
1940 | #define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ | ||
1941 | #define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */ | ||
1942 | |||
1943 | /* | ||
1944 | * PHY current RSSI register [5111+] | ||
1945 | */ | ||
1946 | #define AR5K_PHY_CURRENT_RSSI 0x9c1c | ||
1947 | |||
1948 | /* | ||
1949 | * PHY PCDAC TX power table | ||
1950 | */ | ||
1951 | #define AR5K_PHY_PCDAC_TXPOWER_BASE_5211 0xa180 | ||
1952 | #define AR5K_PHY_PCDAC_TXPOWER_BASE_5413 0xa280 | ||
1953 | #define AR5K_PHY_PCDAC_TXPOWER_BASE (ah->ah_radio >= AR5K_RF5413 ? \ | ||
1954 | AR5K_PHY_PCDAC_TXPOWER_BASE_5413 :\ | ||
1955 | AR5K_PHY_PCDAC_TXPOWER_BASE_5211) | ||
1956 | #define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2)) | ||
1957 | |||
1958 | /* | ||
1959 | * PHY mode register [5111+] | ||
1960 | */ | ||
1961 | #define AR5K_PHY_MODE 0x0a200 /* Register address */ | ||
1962 | #define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation mask*/ | ||
1963 | #define AR5K_PHY_MODE_MOD_OFDM 0 | ||
1964 | #define AR5K_PHY_MODE_MOD_CCK 1 | ||
1965 | #define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode mask */ | ||
1966 | #define AR5K_PHY_MODE_FREQ_5GHZ 0 | ||
1967 | #define AR5K_PHY_MODE_FREQ_2GHZ 2 | ||
1968 | #define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Dynamic OFDM/CCK mode mask [5112+] */ | ||
1969 | #define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */ | ||
1970 | #define AR5K_PHY_MODE_RAD_RF5111 0 | ||
1971 | #define AR5K_PHY_MODE_RAD_RF5112 8 | ||
1972 | #define AR5K_PHY_MODE_XR 0x00000010 /* [5112+] */ | ||
1973 | |||
1974 | /* | ||
1975 | * PHY CCK transmit control register [5111+ (?)] | ||
1976 | */ | ||
1977 | #define AR5K_PHY_CCKTXCTL 0xa204 | ||
1978 | #define AR5K_PHY_CCKTXCTL_WORLD 0x00000000 | ||
1979 | #define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010 | ||
1980 | |||
1981 | /* | ||
1982 | * PHY 2GHz gain register [5111+] | ||
1983 | */ | ||
1984 | #define AR5K_PHY_GAIN_2GHZ 0xa20c | ||
1985 | #define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 | ||
1986 | #define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 | ||
1987 | #define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c | ||
diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c new file mode 100644 index 000000000000..e851957dacfd --- /dev/null +++ b/drivers/net/wireless/ath5k/regdom.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * Basic regulation domain extensions for the IEEE 802.11 stack | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/string.h> | ||
23 | |||
24 | #include "regdom.h" | ||
25 | |||
26 | static const struct ath5k_regdommap { | ||
27 | enum ath5k_regdom dmn; | ||
28 | enum ath5k_regdom dmn5; | ||
29 | enum ath5k_regdom dmn2; | ||
30 | } r_map[] = { | ||
31 | { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG }, | ||
32 | { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, | ||
33 | { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, | ||
34 | { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, | ||
35 | { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, | ||
36 | { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, | ||
37 | { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, | ||
38 | { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, | ||
39 | { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, | ||
40 | { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 }, | ||
41 | { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, | ||
42 | { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, | ||
43 | { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, | ||
44 | { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, | ||
45 | { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, | ||
46 | { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, | ||
47 | { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, | ||
48 | { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, | ||
49 | { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, | ||
50 | { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 }, | ||
51 | { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, | ||
52 | { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, | ||
53 | { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, | ||
54 | { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, | ||
55 | { DMN_APL_NULL, DMN_APL1, DMN_NULL }, | ||
56 | { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, | ||
57 | { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, | ||
58 | { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, | ||
59 | { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, | ||
60 | { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, | ||
61 | { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, | ||
62 | { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, | ||
63 | { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, | ||
64 | { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, | ||
65 | { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, | ||
66 | { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, | ||
67 | { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, | ||
68 | { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, | ||
69 | { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD }, | ||
70 | { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD }, | ||
71 | { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD }, | ||
72 | { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD }, | ||
73 | { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD }, | ||
74 | { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD }, | ||
75 | { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD }, | ||
76 | { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD }, | ||
77 | { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD }, | ||
78 | { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD }, | ||
79 | { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD }, | ||
80 | }; | ||
81 | |||
82 | enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz) | ||
83 | { | ||
84 | unsigned int i; | ||
85 | |||
86 | for (i = 0; i < ARRAY_SIZE(r_map); i++) { | ||
87 | if (r_map[i].dmn == dmn) { | ||
88 | if (mhz >= 2000 && mhz <= 3000) | ||
89 | return r_map[i].dmn2; | ||
90 | if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN && | ||
91 | mhz <= IEEE80211_CHANNELS_5GHZ_MAX) | ||
92 | return r_map[i].dmn5; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return DMN_DEBUG; | ||
97 | } | ||
98 | |||
99 | u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee) | ||
100 | { | ||
101 | u32 regdomain = (u32)ieee; | ||
102 | |||
103 | /* | ||
104 | * Use the default regulation domain if the value is empty | ||
105 | * or not supported by the net80211 regulation code. | ||
106 | */ | ||
107 | if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) == | ||
108 | DMN_DEBUG) | ||
109 | return (u16)AR5K_TUNE_REGDOMAIN; | ||
110 | |||
111 | /* It is supported, just return the value */ | ||
112 | return regdomain; | ||
113 | } | ||
114 | |||
115 | enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain) | ||
116 | { | ||
117 | enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain; | ||
118 | |||
119 | return ieee; | ||
120 | } | ||
121 | |||
diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h new file mode 100644 index 000000000000..f7d3c66e594e --- /dev/null +++ b/drivers/net/wireless/ath5k/regdom.h | |||
@@ -0,0 +1,500 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _IEEE80211_REGDOMAIN_H_ | ||
18 | #define _IEEE80211_REGDOMAIN_H_ | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | |||
22 | /* Default regulation domain if stored value EEPROM value is invalid */ | ||
23 | #define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */ | ||
24 | #define AR5K_TUNE_CTRY CTRY_DEFAULT | ||
25 | |||
26 | |||
27 | enum ath5k_regdom { | ||
28 | DMN_DEFAULT = 0x00, | ||
29 | DMN_NULL_WORLD = 0x03, | ||
30 | DMN_NULL_ETSIB = 0x07, | ||
31 | DMN_NULL_ETSIC = 0x08, | ||
32 | DMN_FCC1_FCCA = 0x10, | ||
33 | DMN_FCC1_WORLD = 0x11, | ||
34 | DMN_FCC2_FCCA = 0x20, | ||
35 | DMN_FCC2_WORLD = 0x21, | ||
36 | DMN_FCC2_ETSIC = 0x22, | ||
37 | DMN_FRANCE_NULL = 0x31, | ||
38 | DMN_FCC3_FCCA = 0x3A, | ||
39 | DMN_ETSI1_WORLD = 0x37, | ||
40 | DMN_ETSI3_ETSIA = 0x32, | ||
41 | DMN_ETSI2_WORLD = 0x35, | ||
42 | DMN_ETSI3_WORLD = 0x36, | ||
43 | DMN_ETSI4_WORLD = 0x30, | ||
44 | DMN_ETSI4_ETSIC = 0x38, | ||
45 | DMN_ETSI5_WORLD = 0x39, | ||
46 | DMN_ETSI6_WORLD = 0x34, | ||
47 | DMN_ETSI_NULL = 0x33, | ||
48 | DMN_MKK1_MKKA = 0x40, | ||
49 | DMN_MKK1_MKKB = 0x41, | ||
50 | DMN_APL4_WORLD = 0x42, | ||
51 | DMN_MKK2_MKKA = 0x43, | ||
52 | DMN_APL_NULL = 0x44, | ||
53 | DMN_APL2_WORLD = 0x45, | ||
54 | DMN_APL2_APLC = 0x46, | ||
55 | DMN_APL3_WORLD = 0x47, | ||
56 | DMN_MKK1_FCCA = 0x48, | ||
57 | DMN_APL2_APLD = 0x49, | ||
58 | DMN_MKK1_MKKA1 = 0x4A, | ||
59 | DMN_MKK1_MKKA2 = 0x4B, | ||
60 | DMN_APL1_WORLD = 0x52, | ||
61 | DMN_APL1_FCCA = 0x53, | ||
62 | DMN_APL1_APLA = 0x54, | ||
63 | DMN_APL1_ETSIC = 0x55, | ||
64 | DMN_APL2_ETSIC = 0x56, | ||
65 | DMN_APL5_WORLD = 0x58, | ||
66 | DMN_WOR0_WORLD = 0x60, | ||
67 | DMN_WOR1_WORLD = 0x61, | ||
68 | DMN_WOR2_WORLD = 0x62, | ||
69 | DMN_WOR3_WORLD = 0x63, | ||
70 | DMN_WOR4_WORLD = 0x64, | ||
71 | DMN_WOR5_ETSIC = 0x65, | ||
72 | DMN_WOR01_WORLD = 0x66, | ||
73 | DMN_WOR02_WORLD = 0x67, | ||
74 | DMN_EU1_WORLD = 0x68, | ||
75 | DMN_WOR9_WORLD = 0x69, | ||
76 | DMN_WORA_WORLD = 0x6A, | ||
77 | |||
78 | DMN_APL1 = 0xf0000001, | ||
79 | DMN_APL2 = 0xf0000002, | ||
80 | DMN_APL3 = 0xf0000004, | ||
81 | DMN_APL4 = 0xf0000008, | ||
82 | DMN_APL5 = 0xf0000010, | ||
83 | DMN_ETSI1 = 0xf0000020, | ||
84 | DMN_ETSI2 = 0xf0000040, | ||
85 | DMN_ETSI3 = 0xf0000080, | ||
86 | DMN_ETSI4 = 0xf0000100, | ||
87 | DMN_ETSI5 = 0xf0000200, | ||
88 | DMN_ETSI6 = 0xf0000400, | ||
89 | DMN_ETSIA = 0xf0000800, | ||
90 | DMN_ETSIB = 0xf0001000, | ||
91 | DMN_ETSIC = 0xf0002000, | ||
92 | DMN_FCC1 = 0xf0004000, | ||
93 | DMN_FCC2 = 0xf0008000, | ||
94 | DMN_FCC3 = 0xf0010000, | ||
95 | DMN_FCCA = 0xf0020000, | ||
96 | DMN_APLD = 0xf0040000, | ||
97 | DMN_MKK1 = 0xf0080000, | ||
98 | DMN_MKK2 = 0xf0100000, | ||
99 | DMN_MKKA = 0xf0200000, | ||
100 | DMN_NULL = 0xf0400000, | ||
101 | DMN_WORLD = 0xf0800000, | ||
102 | DMN_DEBUG = 0xf1000000 /* used for debugging */ | ||
103 | }; | ||
104 | |||
105 | #define IEEE80211_DMN(_d) ((_d) & ~0xf0000000) | ||
106 | |||
107 | enum ath5k_countrycode { | ||
108 | CTRY_DEFAULT = 0, /* Default domain (NA) */ | ||
109 | CTRY_ALBANIA = 8, /* Albania */ | ||
110 | CTRY_ALGERIA = 12, /* Algeria */ | ||
111 | CTRY_ARGENTINA = 32, /* Argentina */ | ||
112 | CTRY_ARMENIA = 51, /* Armenia */ | ||
113 | CTRY_AUSTRALIA = 36, /* Australia */ | ||
114 | CTRY_AUSTRIA = 40, /* Austria */ | ||
115 | CTRY_AZERBAIJAN = 31, /* Azerbaijan */ | ||
116 | CTRY_BAHRAIN = 48, /* Bahrain */ | ||
117 | CTRY_BELARUS = 112, /* Belarus */ | ||
118 | CTRY_BELGIUM = 56, /* Belgium */ | ||
119 | CTRY_BELIZE = 84, /* Belize */ | ||
120 | CTRY_BOLIVIA = 68, /* Bolivia */ | ||
121 | CTRY_BRAZIL = 76, /* Brazil */ | ||
122 | CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ | ||
123 | CTRY_BULGARIA = 100, /* Bulgaria */ | ||
124 | CTRY_CANADA = 124, /* Canada */ | ||
125 | CTRY_CHILE = 152, /* Chile */ | ||
126 | CTRY_CHINA = 156, /* People's Republic of China */ | ||
127 | CTRY_COLOMBIA = 170, /* Colombia */ | ||
128 | CTRY_COSTA_RICA = 188, /* Costa Rica */ | ||
129 | CTRY_CROATIA = 191, /* Croatia */ | ||
130 | CTRY_CYPRUS = 196, /* Cyprus */ | ||
131 | CTRY_CZECH = 203, /* Czech Republic */ | ||
132 | CTRY_DENMARK = 208, /* Denmark */ | ||
133 | CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ | ||
134 | CTRY_ECUADOR = 218, /* Ecuador */ | ||
135 | CTRY_EGYPT = 818, /* Egypt */ | ||
136 | CTRY_EL_SALVADOR = 222, /* El Salvador */ | ||
137 | CTRY_ESTONIA = 233, /* Estonia */ | ||
138 | CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ | ||
139 | CTRY_FINLAND = 246, /* Finland */ | ||
140 | CTRY_FRANCE = 250, /* France */ | ||
141 | CTRY_FRANCE2 = 255, /* France2 */ | ||
142 | CTRY_GEORGIA = 268, /* Georgia */ | ||
143 | CTRY_GERMANY = 276, /* Germany */ | ||
144 | CTRY_GREECE = 300, /* Greece */ | ||
145 | CTRY_GUATEMALA = 320, /* Guatemala */ | ||
146 | CTRY_HONDURAS = 340, /* Honduras */ | ||
147 | CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ | ||
148 | CTRY_HUNGARY = 348, /* Hungary */ | ||
149 | CTRY_ICELAND = 352, /* Iceland */ | ||
150 | CTRY_INDIA = 356, /* India */ | ||
151 | CTRY_INDONESIA = 360, /* Indonesia */ | ||
152 | CTRY_IRAN = 364, /* Iran */ | ||
153 | CTRY_IRAQ = 368, /* Iraq */ | ||
154 | CTRY_IRELAND = 372, /* Ireland */ | ||
155 | CTRY_ISRAEL = 376, /* Israel */ | ||
156 | CTRY_ITALY = 380, /* Italy */ | ||
157 | CTRY_JAMAICA = 388, /* Jamaica */ | ||
158 | CTRY_JAPAN = 392, /* Japan */ | ||
159 | CTRY_JAPAN1 = 393, /* Japan (JP1) */ | ||
160 | CTRY_JAPAN2 = 394, /* Japan (JP0) */ | ||
161 | CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ | ||
162 | CTRY_JAPAN4 = 396, /* Japan (JE1) */ | ||
163 | CTRY_JAPAN5 = 397, /* Japan (JE2) */ | ||
164 | CTRY_JORDAN = 400, /* Jordan */ | ||
165 | CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ | ||
166 | CTRY_KENYA = 404, /* Kenya */ | ||
167 | CTRY_KOREA_NORTH = 408, /* North Korea */ | ||
168 | CTRY_KOREA_ROC = 410, /* South Korea */ | ||
169 | CTRY_KOREA_ROC2 = 411, /* South Korea */ | ||
170 | CTRY_KUWAIT = 414, /* Kuwait */ | ||
171 | CTRY_LATVIA = 428, /* Latvia */ | ||
172 | CTRY_LEBANON = 422, /* Lebanon */ | ||
173 | CTRY_LIBYA = 434, /* Libya */ | ||
174 | CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ | ||
175 | CTRY_LITHUANIA = 440, /* Lithuania */ | ||
176 | CTRY_LUXEMBOURG = 442, /* Luxembourg */ | ||
177 | CTRY_MACAU = 446, /* Macau */ | ||
178 | CTRY_MACEDONIA = 807, /* Republic of Macedonia */ | ||
179 | CTRY_MALAYSIA = 458, /* Malaysia */ | ||
180 | CTRY_MEXICO = 484, /* Mexico */ | ||
181 | CTRY_MONACO = 492, /* Principality of Monaco */ | ||
182 | CTRY_MOROCCO = 504, /* Morocco */ | ||
183 | CTRY_NETHERLANDS = 528, /* Netherlands */ | ||
184 | CTRY_NEW_ZEALAND = 554, /* New Zealand */ | ||
185 | CTRY_NICARAGUA = 558, /* Nicaragua */ | ||
186 | CTRY_NORWAY = 578, /* Norway */ | ||
187 | CTRY_OMAN = 512, /* Oman */ | ||
188 | CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ | ||
189 | CTRY_PANAMA = 591, /* Panama */ | ||
190 | CTRY_PARAGUAY = 600, /* Paraguay */ | ||
191 | CTRY_PERU = 604, /* Peru */ | ||
192 | CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ | ||
193 | CTRY_POLAND = 616, /* Poland */ | ||
194 | CTRY_PORTUGAL = 620, /* Portugal */ | ||
195 | CTRY_PUERTO_RICO = 630, /* Puerto Rico */ | ||
196 | CTRY_QATAR = 634, /* Qatar */ | ||
197 | CTRY_ROMANIA = 642, /* Romania */ | ||
198 | CTRY_RUSSIA = 643, /* Russia */ | ||
199 | CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ | ||
200 | CTRY_SINGAPORE = 702, /* Singapore */ | ||
201 | CTRY_SLOVAKIA = 703, /* Slovak Republic */ | ||
202 | CTRY_SLOVENIA = 705, /* Slovenia */ | ||
203 | CTRY_SOUTH_AFRICA = 710, /* South Africa */ | ||
204 | CTRY_SPAIN = 724, /* Spain */ | ||
205 | CTRY_SRI_LANKA = 728, /* Sri Lanka */ | ||
206 | CTRY_SWEDEN = 752, /* Sweden */ | ||
207 | CTRY_SWITZERLAND = 756, /* Switzerland */ | ||
208 | CTRY_SYRIA = 760, /* Syria */ | ||
209 | CTRY_TAIWAN = 158, /* Taiwan */ | ||
210 | CTRY_THAILAND = 764, /* Thailand */ | ||
211 | CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ | ||
212 | CTRY_TUNISIA = 788, /* Tunisia */ | ||
213 | CTRY_TURKEY = 792, /* Turkey */ | ||
214 | CTRY_UAE = 784, /* U.A.E. */ | ||
215 | CTRY_UKRAINE = 804, /* Ukraine */ | ||
216 | CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ | ||
217 | CTRY_UNITED_STATES = 840, /* United States */ | ||
218 | CTRY_URUGUAY = 858, /* Uruguay */ | ||
219 | CTRY_UZBEKISTAN = 860, /* Uzbekistan */ | ||
220 | CTRY_VENEZUELA = 862, /* Venezuela */ | ||
221 | CTRY_VIET_NAM = 704, /* Viet Nam */ | ||
222 | CTRY_YEMEN = 887, /* Yemen */ | ||
223 | CTRY_ZIMBABWE = 716, /* Zimbabwe */ | ||
224 | }; | ||
225 | |||
226 | #define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */ | ||
227 | #define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */ | ||
228 | #define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */ | ||
229 | #define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */ | ||
230 | |||
231 | struct ath5k_regchannel { | ||
232 | u16 chan; | ||
233 | enum ath5k_regdom domain; | ||
234 | u32 mode; | ||
235 | }; | ||
236 | |||
237 | #define IEEE80211_CHANNELS_2GHZ { \ | ||
238 | /*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
239 | /*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
240 | /*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
241 | /*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
242 | /*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
243 | /*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
244 | /*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
245 | /*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
246 | /*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
247 | /*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
248 | /*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
249 | /*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
250 | /*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
251 | \ | ||
252 | /*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
253 | /*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
254 | /*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
255 | \ | ||
256 | /*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
257 | /*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
258 | /*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
259 | /*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
260 | /*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
261 | /*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
262 | /*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
263 | /*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
264 | /*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
265 | /*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
266 | /*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
267 | /*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
268 | /*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
269 | \ | ||
270 | /*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
271 | /*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
272 | /*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
273 | /*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
274 | /*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
275 | /*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
276 | /*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
277 | /*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
278 | /*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
279 | /*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
280 | /*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
281 | \ | ||
282 | /*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
283 | /*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
284 | /*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
285 | /*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
286 | /*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
287 | /*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
288 | /*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
289 | /*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
290 | /*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
291 | /*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
292 | /*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
293 | /*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
294 | /*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
295 | /*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \ | ||
296 | \ | ||
297 | /*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
298 | /*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
299 | /*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
300 | /*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
301 | /*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
302 | /*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
303 | /*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
304 | /*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
305 | /*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
306 | /*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
307 | /*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
308 | /*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
309 | /*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
310 | } | ||
311 | |||
312 | #define IEEE80211_CHANNELS_5GHZ { \ | ||
313 | /*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \ | ||
314 | /*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \ | ||
315 | /*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \ | ||
316 | /*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \ | ||
317 | /*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \ | ||
318 | \ | ||
319 | /*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \ | ||
320 | /*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \ | ||
321 | /*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \ | ||
322 | /*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \ | ||
323 | \ | ||
324 | /*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \ | ||
325 | /*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \ | ||
326 | /*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \ | ||
327 | /*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \ | ||
328 | /*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \ | ||
329 | /*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \ | ||
330 | /*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \ | ||
331 | \ | ||
332 | /*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \ | ||
333 | /*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \ | ||
334 | /*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \ | ||
335 | /*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \ | ||
336 | /*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \ | ||
337 | /*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \ | ||
338 | /*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \ | ||
339 | /*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \ | ||
340 | /*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \ | ||
341 | \ | ||
342 | /*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \ | ||
343 | /*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \ | ||
344 | /*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \ | ||
345 | /*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \ | ||
346 | /*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \ | ||
347 | \ | ||
348 | /*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
349 | /*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
350 | /*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
351 | /*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
352 | /*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
353 | /*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
354 | /*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
355 | /*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
356 | /*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
357 | /*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
358 | /*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
359 | /*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
360 | /*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
361 | /*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
362 | /*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
363 | /*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
364 | /*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
365 | /*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
366 | /*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
367 | \ | ||
368 | /*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
369 | /*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
370 | /*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
371 | /*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
372 | \ | ||
373 | /*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
374 | /*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
375 | /*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
376 | /*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
377 | /*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
378 | /*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
379 | /*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
380 | /*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
381 | \ | ||
382 | /*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
383 | /*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
384 | /*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
385 | /*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
386 | /*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
387 | /*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
388 | /*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
389 | /*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
390 | \ | ||
391 | /*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
392 | /*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
393 | /*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
394 | /*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
395 | \ | ||
396 | /*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
397 | /*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
398 | /*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
399 | /*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
400 | /*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
401 | /*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
402 | /*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
403 | /*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
404 | /*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
405 | /*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
406 | /*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
407 | /*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
408 | /*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
409 | /*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
410 | /*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
411 | /*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
412 | /*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
413 | \ | ||
414 | /*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \ | ||
415 | /*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \ | ||
416 | /*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
417 | /*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \ | ||
418 | /*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \ | ||
419 | /*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
420 | /*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \ | ||
421 | /*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \ | ||
422 | /*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
423 | /*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \ | ||
424 | /*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \ | ||
425 | /*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \ | ||
426 | /*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
427 | /*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \ | ||
428 | /*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \ | ||
429 | /*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
430 | /*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \ | ||
431 | /*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \ | ||
432 | \ | ||
433 | /*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \ | ||
434 | /*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \ | ||
435 | /*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \ | ||
436 | /*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \ | ||
437 | /*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \ | ||
438 | /*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \ | ||
439 | /*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \ | ||
440 | /*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \ | ||
441 | /*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \ | ||
442 | /*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \ | ||
443 | /*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \ | ||
444 | /*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \ | ||
445 | /*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \ | ||
446 | \ | ||
447 | /*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \ | ||
448 | /*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \ | ||
449 | /*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
450 | /*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \ | ||
451 | /*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \ | ||
452 | /*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
453 | /*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \ | ||
454 | /*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \ | ||
455 | /*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
456 | /*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \ | ||
457 | /*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \ | ||
458 | /*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \ | ||
459 | /*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \ | ||
460 | /*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \ | ||
461 | /*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \ | ||
462 | /*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \ | ||
463 | /*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \ | ||
464 | /*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \ | ||
465 | /*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \ | ||
466 | /*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \ | ||
467 | /*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \ | ||
468 | /*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \ | ||
469 | /*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \ | ||
470 | /*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
471 | /*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \ | ||
472 | /*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \ | ||
473 | /*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
474 | /*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \ | ||
475 | /*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \ | ||
476 | \ | ||
477 | /*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \ | ||
478 | /*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \ | ||
479 | /*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \ | ||
480 | /*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \ | ||
481 | \ | ||
482 | /*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \ | ||
483 | /*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \ | ||
484 | /*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \ | ||
485 | /*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \ | ||
486 | /*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \ | ||
487 | /*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \ | ||
488 | /*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \ | ||
489 | \ | ||
490 | /*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \ | ||
491 | /*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \ | ||
492 | /*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \ | ||
493 | /*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \ | ||
494 | } | ||
495 | |||
496 | enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16); | ||
497 | u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee); | ||
498 | enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain); | ||
499 | |||
500 | #endif | ||