aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/pcu.c
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-08-29 15:45:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-05 16:15:24 -0400
commitc6e387a214f4b2c4bd48020409e366c133385d98 (patch)
tree11fd58fd71e113a62d05f6f191771ca3d7d544f0 /drivers/net/wireless/ath5k/pcu.c
parentfa9abe050d0a018b888fce61a4353afab17b0860 (diff)
ath5k: HW code cleanup
* No code changes... * Split hw.c to multiple files for better maintenance and add some documentation on each file code is going to grow soon (eeprom.c for example is going to get much stuff currently developed on ath_info) so it's better this way. * Rename following functions to maintain naming scheme: ah_setup_xtx_desc -> ah_setup_mrr_tx_desc (Because xtx doesn't say much, it's actually a multi-rate-retry tx descriptor) ath5k_hw_put_tx/rx_buf - > ath5k_hw_set_tx/rxdp ath5k_hw_get_tx/rx_buf -> ath5k_hw_get_tx/rxdp (We don't put any "buf" we set descriptor pointers on hw) ath5k_hw_tx_start -> ath5k_hw_start_tx_dma ath5k_hw_start_rx -> ath5k_hw_start_rx_dma ath5k_hw_stop_pcu_recv -> ath5k_hw_stop_rx_pcu (It's easier this way to identify them, we also have ath5k_hw_start_rx_pcu which completes the set) ath5k_hw_set_intr -> ath5k_hw_set_imr (As in get_isr we set imr here, not "intr") * Move ath5k_hw_setup_rx_desc on ah->ah_setup_rx_desc so we can include support for different rx descriptors in the future * Further cleanups so that checkpatch doesn't complain (only some > 80 col warnings for eeprom.h and reg.h as usual due to comments) Tested on 5211 and 5213 cards and works ok. Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Acked-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/pcu.c')
-rw-r--r--drivers/net/wireless/ath5k/pcu.c1002
1 files changed, 1002 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
new file mode 100644
index 000000000000..5a896d1e2a2b
--- /dev/null
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -0,0 +1,1002 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org>
5 * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
6 * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
7 * Copyright (c) 2007-2008 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* Protocol Control Unit Functions *
25\*********************************/
26
27#include "ath5k.h"
28#include "reg.h"
29#include "debug.h"
30#include "base.h"
31
32/*******************\
33* Generic functions *
34\*******************/
35
36/**
37 * ath5k_hw_set_opmode - Set PCU operating mode
38 *
39 * @ah: The &struct ath5k_hw
40 *
41 * Initialize PCU for the various operating modes (AP/STA etc)
42 *
43 * NOTE: ah->ah_op_mode must be set before calling this.
44 */
45int ath5k_hw_set_opmode(struct ath5k_hw *ah)
46{
47 u32 pcu_reg, beacon_reg, low_id, high_id;
48
49 pcu_reg = 0;
50 beacon_reg = 0;
51
52 ATH5K_TRACE(ah->ah_sc);
53
54 switch (ah->ah_op_mode) {
55 case IEEE80211_IF_TYPE_IBSS:
56 pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
57 (ah->ah_version == AR5K_AR5210 ?
58 AR5K_STA_ID1_NO_PSPOLL : 0);
59 beacon_reg |= AR5K_BCR_ADHOC;
60 break;
61
62 case IEEE80211_IF_TYPE_AP:
63 case IEEE80211_IF_TYPE_MESH_POINT:
64 pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
65 (ah->ah_version == AR5K_AR5210 ?
66 AR5K_STA_ID1_NO_PSPOLL : 0);
67 beacon_reg |= AR5K_BCR_AP;
68 break;
69
70 case IEEE80211_IF_TYPE_STA:
71 pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
72 (ah->ah_version == AR5K_AR5210 ?
73 AR5K_STA_ID1_PWR_SV : 0);
74 case IEEE80211_IF_TYPE_MNTR:
75 pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
76 (ah->ah_version == AR5K_AR5210 ?
77 AR5K_STA_ID1_NO_PSPOLL : 0);
78 break;
79
80 default:
81 return -EINVAL;
82 }
83
84 /*
85 * Set PCU registers
86 */
87 low_id = AR5K_LOW_ID(ah->ah_sta_id);
88 high_id = AR5K_HIGH_ID(ah->ah_sta_id);
89 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
90 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
91
92 /*
93 * Set Beacon Control Register on 5210
94 */
95 if (ah->ah_version == AR5K_AR5210)
96 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
97
98 return 0;
99}
100
101/**
102 * ath5k_hw_update - Update mib counters (mac layer statistics)
103 *
104 * @ah: The &struct ath5k_hw
105 * @stats: The &struct ieee80211_low_level_stats we use to track
106 * statistics on the driver
107 *
108 * Reads MIB counters from PCU and updates sw statistics. Must be
109 * called after a MIB interrupt.
110 */
111void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
112 struct ieee80211_low_level_stats *stats)
113{
114 ATH5K_TRACE(ah->ah_sc);
115
116 /* Read-And-Clear */
117 stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
118 stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
119 stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
120 stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
121
122 /* XXX: Should we use this to track beacon count ?
123 * -we read it anyway to clear the register */
124 ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
125
126 /* Reset profile count registers on 5212*/
127 if (ah->ah_version == AR5K_AR5212) {
128 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
129 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
130 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
131 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
132 }
133}
134
135/**
136 * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
137 *
138 * @ah: The &struct ath5k_hw
139 * @high: Flag to determine if we want to use high transmition rate
140 * for ACKs or not
141 *
142 * If high flag is set, we tell hw to use a set of control rates based on
143 * the current transmition rate (check out control_rates array inside reset.c).
144 * If not hw just uses the lowest rate available for the current modulation
145 * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
146 */
147void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
148{
149 if (ah->ah_version != AR5K_AR5212)
150 return;
151 else {
152 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
153 if (high)
154 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
155 else
156 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
157 }
158}
159
160
161/******************\
162* ACK/CTS Timeouts *
163\******************/
164
165/**
166 * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
167 *
168 * @ah: The &struct ath5k_hw
169 */
170unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
171{
172 ATH5K_TRACE(ah->ah_sc);
173
174 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
175 AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
176}
177
178/**
179 * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
180 *
181 * @ah: The &struct ath5k_hw
182 * @timeout: Timeout in usec
183 */
184int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
185{
186 ATH5K_TRACE(ah->ah_sc);
187 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
188 ah->ah_turbo) <= timeout)
189 return -EINVAL;
190
191 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
192 ath5k_hw_htoclock(timeout, ah->ah_turbo));
193
194 return 0;
195}
196
197/**
198 * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
199 *
200 * @ah: The &struct ath5k_hw
201 */
202unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
203{
204 ATH5K_TRACE(ah->ah_sc);
205 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
206 AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
207}
208
209/**
210 * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
211 *
212 * @ah: The &struct ath5k_hw
213 * @timeout: Timeout in usec
214 */
215int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
216{
217 ATH5K_TRACE(ah->ah_sc);
218 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
219 ah->ah_turbo) <= timeout)
220 return -EINVAL;
221
222 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
223 ath5k_hw_htoclock(timeout, ah->ah_turbo));
224
225 return 0;
226}
227
228
229/****************\
230* BSSID handling *
231\****************/
232
233/**
234 * ath5k_hw_get_lladdr - Get station id
235 *
236 * @ah: The &struct ath5k_hw
237 * @mac: The card's mac address
238 *
239 * Initialize ah->ah_sta_id using the mac address provided
240 * (just a memcpy).
241 *
242 * TODO: Remove it once we merge ath5k_softc and ath5k_hw
243 */
244void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
245{
246 ATH5K_TRACE(ah->ah_sc);
247 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
248}
249
250/**
251 * ath5k_hw_set_lladdr - Set station id
252 *
253 * @ah: The &struct ath5k_hw
254 * @mac: The card's mac address
255 *
256 * Set station id on hw using the provided mac address
257 */
258int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
259{
260 u32 low_id, high_id;
261
262 ATH5K_TRACE(ah->ah_sc);
263 /* Set new station ID */
264 memcpy(ah->ah_sta_id, mac, ETH_ALEN);
265
266 low_id = AR5K_LOW_ID(mac);
267 high_id = AR5K_HIGH_ID(mac);
268
269 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
270 ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
271
272 return 0;
273}
274
275/**
276 * ath5k_hw_set_associd - Set BSSID for association
277 *
278 * @ah: The &struct ath5k_hw
279 * @bssid: BSSID
280 * @assoc_id: Assoc id
281 *
282 * Sets the BSSID which trigers the "SME Join" operation
283 */
284void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
285{
286 u32 low_id, high_id;
287 u16 tim_offset = 0;
288
289 /*
290 * Set simple BSSID mask on 5212
291 */
292 if (ah->ah_version == AR5K_AR5212) {
293 ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
294 ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
295 }
296
297 /*
298 * Set BSSID which triggers the "SME Join" operation
299 */
300 low_id = AR5K_LOW_ID(bssid);
301 high_id = AR5K_HIGH_ID(bssid);
302 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
303 ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
304 AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
305
306 if (assoc_id == 0) {
307 ath5k_hw_disable_pspoll(ah);
308 return;
309 }
310
311 AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
312 tim_offset ? tim_offset + 4 : 0);
313
314 ath5k_hw_enable_pspoll(ah, NULL, 0);
315}
316
317/**
318 * ath5k_hw_set_bssid_mask - filter out bssids we listen
319 *
320 * @ah: the &struct ath5k_hw
321 * @mask: the bssid_mask, a u8 array of size ETH_ALEN
322 *
323 * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
324 * which bits of the interface's MAC address should be looked at when trying
325 * to decide which packets to ACK. In station mode and AP mode with a single
326 * BSS every bit matters since we lock to only one BSS. In AP mode with
327 * multiple BSSes (virtual interfaces) not every bit matters because hw must
328 * accept frames for all BSSes and so we tweak some bits of our mac address
329 * in order to have multiple BSSes.
330 *
331 * NOTE: This is a simple filter and does *not* filter out all
332 * relevant frames. Some frames that are not for us might get ACKed from us
333 * by PCU because they just match the mask.
334 *
335 * When handling multiple BSSes you can get the BSSID mask by computing the
336 * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
337 *
338 * When you do this you are essentially computing the common bits of all your
339 * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
340 * the MAC address to obtain the relevant bits and compare the result with
341 * (frame's BSSID & mask) to see if they match.
342 */
343/*
344 * Simple example: on your card you have have two BSSes you have created with
345 * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
346 * There is another BSSID-03 but you are not part of it. For simplicity's sake,
347 * assuming only 4 bits for a mac address and for BSSIDs you can then have:
348 *
349 * \
350 * MAC: 0001 |
351 * BSSID-01: 0100 | --> Belongs to us
352 * BSSID-02: 1001 |
353 * /
354 * -------------------
355 * BSSID-03: 0110 | --> External
356 * -------------------
357 *
358 * Our bssid_mask would then be:
359 *
360 * On loop iteration for BSSID-01:
361 * ~(0001 ^ 0100) -> ~(0101)
362 * -> 1010
363 * bssid_mask = 1010
364 *
365 * On loop iteration for BSSID-02:
366 * bssid_mask &= ~(0001 ^ 1001)
367 * bssid_mask = (1010) & ~(0001 ^ 1001)
368 * bssid_mask = (1010) & ~(1001)
369 * bssid_mask = (1010) & (0110)
370 * bssid_mask = 0010
371 *
372 * A bssid_mask of 0010 means "only pay attention to the second least
373 * significant bit". This is because its the only bit common
374 * amongst the MAC and all BSSIDs we support. To findout what the real
375 * common bit is we can simply "&" the bssid_mask now with any BSSID we have
376 * or our MAC address (we assume the hardware uses the MAC address).
377 *
378 * Now, suppose there's an incoming frame for BSSID-03:
379 *
380 * IFRAME-01: 0110
381 *
382 * An easy eye-inspeciton of this already should tell you that this frame
383 * will not pass our check. This is beacuse the bssid_mask tells the
384 * hardware to only look at the second least significant bit and the
385 * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
386 * as 1, which does not match 0.
387 *
388 * So with IFRAME-01 we *assume* the hardware will do:
389 *
390 * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
391 * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
392 * --> allow = (0010) == 0000 ? 1 : 0;
393 * --> allow = 0
394 *
395 * Lets now test a frame that should work:
396 *
397 * IFRAME-02: 0001 (we should allow)
398 *
399 * allow = (0001 & 1010) == 1010
400 *
401 * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
402 * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
403 * --> allow = (0010) == (0010)
404 * --> allow = 1
405 *
406 * Other examples:
407 *
408 * IFRAME-03: 0100 --> allowed
409 * IFRAME-04: 1001 --> allowed
410 * IFRAME-05: 1101 --> allowed but its not for us!!!
411 *
412 */
413int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
414{
415 u32 low_id, high_id;
416 ATH5K_TRACE(ah->ah_sc);
417
418 if (ah->ah_version == AR5K_AR5212) {
419 low_id = AR5K_LOW_ID(mask);
420 high_id = AR5K_HIGH_ID(mask);
421
422 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
423 ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
424
425 return 0;
426 }
427
428 return -EIO;
429}
430
431
432/************\
433* RX Control *
434\************/
435
436/**
437 * ath5k_hw_start_rx_pcu - Start RX engine
438 *
439 * @ah: The &struct ath5k_hw
440 *
441 * Starts RX engine on PCU so that hw can process RXed frames
442 * (ACK etc).
443 *
444 * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
445 * TODO: Init ANI here
446 */
447void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
448{
449 ATH5K_TRACE(ah->ah_sc);
450 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
451}
452
453/**
454 * at5k_hw_stop_rx_pcu - Stop RX engine
455 *
456 * @ah: The &struct ath5k_hw
457 *
458 * Stops RX engine on PCU
459 *
460 * TODO: Detach ANI here
461 */
462void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
463{
464 ATH5K_TRACE(ah->ah_sc);
465 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
466}
467
468/*
469 * Set multicast filter
470 */
471void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
472{
473 ATH5K_TRACE(ah->ah_sc);
474 /* Set the multicat filter */
475 ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
476 ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
477}
478
479/*
480 * Set multicast filter by index
481 */
482int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
483{
484
485 ATH5K_TRACE(ah->ah_sc);
486 if (index >= 64)
487 return -EINVAL;
488 else if (index >= 32)
489 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
490 (1 << (index - 32)));
491 else
492 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
493
494 return 0;
495}
496
497/*
498 * Clear Multicast filter by index
499 */
500int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
501{
502
503 ATH5K_TRACE(ah->ah_sc);
504 if (index >= 64)
505 return -EINVAL;
506 else if (index >= 32)
507 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
508 (1 << (index - 32)));
509 else
510 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
511
512 return 0;
513}
514
515/**
516 * ath5k_hw_get_rx_filter - Get current rx filter
517 *
518 * @ah: The &struct ath5k_hw
519 *
520 * Returns the RX filter by reading rx filter and
521 * phy error filter registers. RX filter is used
522 * to set the allowed frame types that PCU will accept
523 * and pass to the driver. For a list of frame types
524 * check out reg.h.
525 */
526u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
527{
528 u32 data, filter = 0;
529
530 ATH5K_TRACE(ah->ah_sc);
531 filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
532
533 /*Radar detection for 5212*/
534 if (ah->ah_version == AR5K_AR5212) {
535 data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
536
537 if (data & AR5K_PHY_ERR_FIL_RADAR)
538 filter |= AR5K_RX_FILTER_RADARERR;
539 if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
540 filter |= AR5K_RX_FILTER_PHYERR;
541 }
542
543 return filter;
544}
545
546/**
547 * ath5k_hw_set_rx_filter - Set rx filter
548 *
549 * @ah: The &struct ath5k_hw
550 * @filter: RX filter mask (see reg.h)
551 *
552 * Sets RX filter register and also handles PHY error filter
553 * register on 5212 and newer chips so that we have proper PHY
554 * error reporting.
555 */
556void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
557{
558 u32 data = 0;
559
560 ATH5K_TRACE(ah->ah_sc);
561
562 /* Set PHY error filter register on 5212*/
563 if (ah->ah_version == AR5K_AR5212) {
564 if (filter & AR5K_RX_FILTER_RADARERR)
565 data |= AR5K_PHY_ERR_FIL_RADAR;
566 if (filter & AR5K_RX_FILTER_PHYERR)
567 data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
568 }
569
570 /*
571 * The AR5210 uses promiscous mode to detect radar activity
572 */
573 if (ah->ah_version == AR5K_AR5210 &&
574 (filter & AR5K_RX_FILTER_RADARERR)) {
575 filter &= ~AR5K_RX_FILTER_RADARERR;
576 filter |= AR5K_RX_FILTER_PROM;
577 }
578
579 /*Zero length DMA*/
580 if (data)
581 AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
582 else
583 AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
584
585 /*Write RX Filter register*/
586 ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
587
588 /*Write PHY error filter register on 5212*/
589 if (ah->ah_version == AR5K_AR5212)
590 ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
591
592}
593
594
595/****************\
596* Beacon control *
597\****************/
598
599/**
600 * ath5k_hw_get_tsf32 - Get a 32bit TSF
601 *
602 * @ah: The &struct ath5k_hw
603 *
604 * Returns lower 32 bits of current TSF
605 */
606u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
607{
608 ATH5K_TRACE(ah->ah_sc);
609 return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
610}
611
612/**
613 * ath5k_hw_get_tsf64 - Get the full 64bit TSF
614 *
615 * @ah: The &struct ath5k_hw
616 *
617 * Returns the current TSF
618 */
619u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
620{
621 u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
622 ATH5K_TRACE(ah->ah_sc);
623
624 return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
625}
626
627/**
628 * ath5k_hw_reset_tsf - Force a TSF reset
629 *
630 * @ah: The &struct ath5k_hw
631 *
632 * Forces a TSF reset on PCU
633 */
634void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
635{
636 ATH5K_TRACE(ah->ah_sc);
637 AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF);
638}
639
640/*
641 * Initialize beacon timers
642 */
643void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
644{
645 u32 timer1, timer2, timer3;
646
647 ATH5K_TRACE(ah->ah_sc);
648 /*
649 * Set the additional timers by mode
650 */
651 switch (ah->ah_op_mode) {
652 case IEEE80211_IF_TYPE_STA:
653 if (ah->ah_version == AR5K_AR5210) {
654 timer1 = 0xffffffff;
655 timer2 = 0xffffffff;
656 } else {
657 timer1 = 0x0000ffff;
658 timer2 = 0x0007ffff;
659 }
660 break;
661
662 default:
663 timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
664 timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
665 }
666
667 timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
668
669 /*
670 * Set the beacon register and enable all timers.
671 * (next beacon, DMA beacon, software beacon, ATIM window time)
672 */
673 ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
674 ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
675 ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
676 ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
677
678 ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
679 AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
680 AR5K_BEACON);
681}
682
683#if 0
684/*
685 * Set beacon timers
686 */
687int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
688 const struct ath5k_beacon_state *state)
689{
690 u32 cfp_period, next_cfp, dtim, interval, next_beacon;
691
692 /*
693 * TODO: should be changed through *state
694 * review struct ath5k_beacon_state struct
695 *
696 * XXX: These are used for cfp period bellow, are they
697 * ok ? Is it O.K. for tsf here to be 0 or should we use
698 * get_tsf ?
699 */
700 u32 dtim_count = 0; /* XXX */
701 u32 cfp_count = 0; /* XXX */
702 u32 tsf = 0; /* XXX */
703
704 ATH5K_TRACE(ah->ah_sc);
705 /* Return on an invalid beacon state */
706 if (state->bs_interval < 1)
707 return -EINVAL;
708
709 interval = state->bs_interval;
710 dtim = state->bs_dtim_period;
711
712 /*
713 * PCF support?
714 */
715 if (state->bs_cfp_period > 0) {
716 /*
717 * Enable PCF mode and set the CFP
718 * (Contention Free Period) and timer registers
719 */
720 cfp_period = state->bs_cfp_period * state->bs_dtim_period *
721 state->bs_interval;
722 next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
723 state->bs_interval;
724
725 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
726 AR5K_STA_ID1_DEFAULT_ANTENNA |
727 AR5K_STA_ID1_PCF);
728 ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
729 ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
730 AR5K_CFP_DUR);
731 ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
732 next_cfp)) << 3, AR5K_TIMER2);
733 } else {
734 /* Disable PCF mode */
735 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
736 AR5K_STA_ID1_DEFAULT_ANTENNA |
737 AR5K_STA_ID1_PCF);
738 }
739
740 /*
741 * Enable the beacon timer register
742 */
743 ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
744
745 /*
746 * Start the beacon timers
747 */
748 ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
749 ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
750 AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
751 AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
752 AR5K_BEACON_PERIOD), AR5K_BEACON);
753
754 /*
755 * Write new beacon miss threshold, if it appears to be valid
756 * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
757 * and return if its not in range. We can test this by reading value and
758 * setting value to a largest value and seeing which values register.
759 */
760
761 AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
762 state->bs_bmiss_threshold);
763
764 /*
765 * Set sleep control register
766 * XXX: Didn't find this in 5210 code but since this register
767 * exists also in ar5k's 5210 headers i leave it as common code.
768 */
769 AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
770 (state->bs_sleep_duration - 3) << 3);
771
772 /*
773 * Set enhanced sleep registers on 5212
774 */
775 if (ah->ah_version == AR5K_AR5212) {
776 if (state->bs_sleep_duration > state->bs_interval &&
777 roundup(state->bs_sleep_duration, interval) ==
778 state->bs_sleep_duration)
779 interval = state->bs_sleep_duration;
780
781 if (state->bs_sleep_duration > dtim && (dtim == 0 ||
782 roundup(state->bs_sleep_duration, dtim) ==
783 state->bs_sleep_duration))
784 dtim = state->bs_sleep_duration;
785
786 if (interval > dtim)
787 return -EINVAL;
788
789 next_beacon = interval == dtim ? state->bs_next_dtim :
790 state->bs_next_beacon;
791
792 ath5k_hw_reg_write(ah,
793 AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
794 AR5K_SLEEP0_NEXT_DTIM) |
795 AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
796 AR5K_SLEEP0_ENH_SLEEP_EN |
797 AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
798
799 ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
800 AR5K_SLEEP1_NEXT_TIM) |
801 AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
802
803 ath5k_hw_reg_write(ah,
804 AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
805 AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
806 }
807
808 return 0;
809}
810
811/*
812 * Reset beacon timers
813 */
814void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
815{
816 ATH5K_TRACE(ah->ah_sc);
817 /*
818 * Disable beacon timer
819 */
820 ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
821
822 /*
823 * Disable some beacon register values
824 */
825 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
826 AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
827 ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
828}
829
830/*
831 * Wait for beacon queue to finish
832 */
833int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
834{
835 unsigned int i;
836 int ret;
837
838 ATH5K_TRACE(ah->ah_sc);
839
840 /* 5210 doesn't have QCU*/
841 if (ah->ah_version == AR5K_AR5210) {
842 /*
843 * Wait for beaconn queue to finish by checking
844 * Control Register and Beacon Status Register.
845 */
846 for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
847 if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
848 ||
849 !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
850 break;
851 udelay(10);
852 }
853
854 /* Timeout... */
855 if (i <= 0) {
856 /*
857 * Re-schedule the beacon queue
858 */
859 ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
860 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
861 AR5K_BCR);
862
863 return -EIO;
864 }
865 ret = 0;
866 } else {
867 /*5211/5212*/
868 ret = ath5k_hw_register_timeout(ah,
869 AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
870 AR5K_QCU_STS_FRMPENDCNT, 0, false);
871
872 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
873 return -EIO;
874 }
875
876 return ret;
877}
878#endif
879
880
881/*********************\
882* Key table functions *
883\*********************/
884
885/*
886 * Reset a key entry on the table
887 */
888int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
889{
890 unsigned int i;
891
892 ATH5K_TRACE(ah->ah_sc);
893 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
894
895 for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
896 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
897
898 /*
899 * Set NULL encryption on AR5212+
900 *
901 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
902 * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
903 *
904 * Note2: Windows driver (ndiswrapper) sets this to
905 * 0x00000714 instead of 0x00000007
906 */
907 if (ah->ah_version > AR5K_AR5211)
908 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
909 AR5K_KEYTABLE_TYPE(entry));
910
911 return 0;
912}
913
914/*
915 * Check if a table entry is valid
916 */
917int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
918{
919 ATH5K_TRACE(ah->ah_sc);
920 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
921
922 /* Check the validation flag at the end of the entry */
923 return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
924 AR5K_KEYTABLE_VALID;
925}
926
927/*
928 * Set a key entry on the table
929 */
930int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
931 const struct ieee80211_key_conf *key, const u8 *mac)
932{
933 unsigned int i;
934 __le32 key_v[5] = {};
935 u32 keytype;
936
937 ATH5K_TRACE(ah->ah_sc);
938
939 /* key->keylen comes in from mac80211 in bytes */
940
941 if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
942 return -EOPNOTSUPP;
943
944 switch (key->keylen) {
945 /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
946 case 40 / 8:
947 memcpy(&key_v[0], key->key, 5);
948 keytype = AR5K_KEYTABLE_TYPE_40;
949 break;
950
951 /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
952 case 104 / 8:
953 memcpy(&key_v[0], &key->key[0], 6);
954 memcpy(&key_v[2], &key->key[6], 6);
955 memcpy(&key_v[4], &key->key[12], 1);
956 keytype = AR5K_KEYTABLE_TYPE_104;
957 break;
958 /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
959 case 128 / 8:
960 memcpy(&key_v[0], &key->key[0], 6);
961 memcpy(&key_v[2], &key->key[6], 6);
962 memcpy(&key_v[4], &key->key[12], 4);
963 keytype = AR5K_KEYTABLE_TYPE_128;
964 break;
965
966 default:
967 return -EINVAL; /* shouldn't happen */
968 }
969
970 for (i = 0; i < ARRAY_SIZE(key_v); i++)
971 ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
972 AR5K_KEYTABLE_OFF(entry, i));
973
974 ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
975
976 return ath5k_hw_set_key_lladdr(ah, entry, mac);
977}
978
979int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
980{
981 u32 low_id, high_id;
982
983 ATH5K_TRACE(ah->ah_sc);
984 /* Invalid entry (key table overflow) */
985 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
986
987 /* MAC may be NULL if it's a broadcast key. In this case no need to
988 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
989 if (unlikely(mac == NULL)) {
990 low_id = 0xffffffff;
991 high_id = 0xffff | AR5K_KEYTABLE_VALID;
992 } else {
993 low_id = AR5K_LOW_ID(mac);
994 high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
995 }
996
997 ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
998 ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
999
1000 return 0;
1001}
1002