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/hw.c | |
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/hw.c')
-rw-r--r-- | drivers/net/wireless/ath5k/hw.c | 4349 |
1 files changed, 4349 insertions, 0 deletions
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 | } | ||