iPXE
ath5k_pcu.c
Go to the documentation of this file.
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 * Lightly modified for iPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
10 *
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 */
24
26FILE_SECBOOT ( FORBIDDEN );
27
28/*********************************\
29* Protocol Control Unit Functions *
30\*********************************/
31
32#include "ath5k.h"
33#include "reg.h"
34#include "base.h"
35
36/*******************\
37* Generic functions *
38\*******************/
39
40/**
41 * ath5k_hw_set_opmode - Set PCU operating mode
42 *
43 * @ah: The &struct ath5k_hw
44 *
45 * Initialize PCU for the various operating modes (AP/STA etc)
46 *
47 * For iPXE we always assume STA mode.
48 */
50{
51 u32 pcu_reg, beacon_reg, low_id, high_id;
52
53
54 /* Preserve rest settings */
55 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
58 | (ah->ah_version == AR5K_AR5210 ?
60
61 beacon_reg = 0;
62
64 | (ah->ah_version == AR5K_AR5210 ?
66
67 /*
68 * Set PCU registers
69 */
70 low_id = AR5K_LOW_ID(ah->ah_sta_id);
71 high_id = AR5K_HIGH_ID(ah->ah_sta_id);
73 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
74
75 /*
76 * Set Beacon Control Register on 5210
77 */
78 if (ah->ah_version == AR5K_AR5210)
79 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
80
81 return 0;
82}
83
84/**
85 * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
86 *
87 * @ah: The &struct ath5k_hw
88 * @high: Flag to determine if we want to use high transmition rate
89 * for ACKs or not
90 *
91 * If high flag is set, we tell hw to use a set of control rates based on
92 * the current transmition rate (check out control_rates array inside reset.c).
93 * If not hw just uses the lowest rate available for the current modulation
94 * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
95 */
97{
98 if (ah->ah_version != AR5K_AR5212)
99 return;
100 else {
102 if (high)
104 else
106 }
107}
108
109
110/******************\
111* ACK/CTS Timeouts *
112\******************/
113
114/**
115 * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
116 *
117 * @ah: The &struct ath5k_hw
118 */
124
125/**
126 * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
127 *
128 * @ah: The &struct ath5k_hw
129 * @timeout: Timeout in usec
130 */
131int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
132{
134 ah->ah_turbo) <= timeout)
135 return -EINVAL;
136
138 ath5k_hw_htoclock(timeout, ah->ah_turbo));
139
140 return 0;
141}
142
143/**
144 * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
145 *
146 * @ah: The &struct ath5k_hw
147 */
153
154/**
155 * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
156 *
157 * @ah: The &struct ath5k_hw
158 * @timeout: Timeout in usec
159 */
160int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
161{
163 ah->ah_turbo) <= timeout)
164 return -EINVAL;
165
167 ath5k_hw_htoclock(timeout, ah->ah_turbo));
168
169 return 0;
170}
171
172
173/****************\
174* BSSID handling *
175\****************/
176
177/**
178 * ath5k_hw_get_lladdr - Get station id
179 *
180 * @ah: The &struct ath5k_hw
181 * @mac: The card's mac address
182 *
183 * Initialize ah->ah_sta_id using the mac address provided
184 * (just a memcpy).
185 *
186 * TODO: Remove it once we merge ath5k_softc and ath5k_hw
187 */
189{
190 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
191}
192
193/**
194 * ath5k_hw_set_lladdr - Set station id
195 *
196 * @ah: The &struct ath5k_hw
197 * @mac: The card's mac address
198 *
199 * Set station id on hw using the provided mac address
200 */
202{
203 u32 low_id, high_id;
204 u32 pcu_reg;
205
206 /* Set new station ID */
207 memcpy(ah->ah_sta_id, mac, ETH_ALEN);
208
209 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
210
211 low_id = AR5K_LOW_ID(mac);
212 high_id = AR5K_HIGH_ID(mac);
213
215 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
216
217 return 0;
218}
219
220/**
221 * ath5k_hw_set_associd - Set BSSID for association
222 *
223 * @ah: The &struct ath5k_hw
224 * @bssid: BSSID
225 * @assoc_id: Assoc id
226 *
227 * Sets the BSSID which trigers the "SME Join" operation
228 */
229void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
230{
231 u32 low_id, high_id;
232
233 /*
234 * Set simple BSSID mask on 5212
235 */
236 if (ah->ah_version == AR5K_AR5212) {
237 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
239 ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
241 }
242
243 /*
244 * Set BSSID which triggers the "SME Join" operation
245 */
246 low_id = AR5K_LOW_ID(bssid);
247 high_id = AR5K_HIGH_ID(bssid);
249 ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
251}
252
253/**
254 * ath5k_hw_set_bssid_mask - filter out bssids we listen
255 *
256 * @ah: the &struct ath5k_hw
257 * @mask: the bssid_mask, a u8 array of size ETH_ALEN
258 *
259 * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
260 * which bits of the interface's MAC address should be looked at when trying
261 * to decide which packets to ACK. In station mode and AP mode with a single
262 * BSS every bit matters since we lock to only one BSS. In AP mode with
263 * multiple BSSes (virtual interfaces) not every bit matters because hw must
264 * accept frames for all BSSes and so we tweak some bits of our mac address
265 * in order to have multiple BSSes.
266 *
267 * NOTE: This is a simple filter and does *not* filter out all
268 * relevant frames. Some frames that are not for us might get ACKed from us
269 * by PCU because they just match the mask.
270 *
271 * When handling multiple BSSes you can get the BSSID mask by computing the
272 * set of ~ ( MAC XOR BSSID ) for all bssids we handle.
273 *
274 * When you do this you are essentially computing the common bits of all your
275 * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
276 * the MAC address to obtain the relevant bits and compare the result with
277 * (frame's BSSID & mask) to see if they match.
278 */
279/*
280 * Simple example: on your card you have have two BSSes you have created with
281 * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
282 * There is another BSSID-03 but you are not part of it. For simplicity's sake,
283 * assuming only 4 bits for a mac address and for BSSIDs you can then have:
284 *
285 * \
286 * MAC: 0001 |
287 * BSSID-01: 0100 | --> Belongs to us
288 * BSSID-02: 1001 |
289 * /
290 * -------------------
291 * BSSID-03: 0110 | --> External
292 * -------------------
293 *
294 * Our bssid_mask would then be:
295 *
296 * On loop iteration for BSSID-01:
297 * ~(0001 ^ 0100) -> ~(0101)
298 * -> 1010
299 * bssid_mask = 1010
300 *
301 * On loop iteration for BSSID-02:
302 * bssid_mask &= ~(0001 ^ 1001)
303 * bssid_mask = (1010) & ~(0001 ^ 1001)
304 * bssid_mask = (1010) & ~(1001)
305 * bssid_mask = (1010) & (0110)
306 * bssid_mask = 0010
307 *
308 * A bssid_mask of 0010 means "only pay attention to the second least
309 * significant bit". This is because its the only bit common
310 * amongst the MAC and all BSSIDs we support. To findout what the real
311 * common bit is we can simply "&" the bssid_mask now with any BSSID we have
312 * or our MAC address (we assume the hardware uses the MAC address).
313 *
314 * Now, suppose there's an incoming frame for BSSID-03:
315 *
316 * IFRAME-01: 0110
317 *
318 * An easy eye-inspeciton of this already should tell you that this frame
319 * will not pass our check. This is beacuse the bssid_mask tells the
320 * hardware to only look at the second least significant bit and the
321 * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
322 * as 1, which does not match 0.
323 *
324 * So with IFRAME-01 we *assume* the hardware will do:
325 *
326 * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
327 * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
328 * --> allow = (0010) == 0000 ? 1 : 0;
329 * --> allow = 0
330 *
331 * Lets now test a frame that should work:
332 *
333 * IFRAME-02: 0001 (we should allow)
334 *
335 * allow = (0001 & 1010) == 1010
336 *
337 * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
338 * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
339 * --> allow = (0010) == (0010)
340 * --> allow = 1
341 *
342 * Other examples:
343 *
344 * IFRAME-03: 0100 --> allowed
345 * IFRAME-04: 1001 --> allowed
346 * IFRAME-05: 1101 --> allowed but its not for us!!!
347 *
348 */
349int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
350{
351 u32 low_id, high_id;
352
353 /* Cache bssid mask so that we can restore it
354 * on reset */
355 memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
356 if (ah->ah_version == AR5K_AR5212) {
357 low_id = AR5K_LOW_ID(mask);
358 high_id = AR5K_HIGH_ID(mask);
359
362
363 return 0;
364 }
365
366 return -EIO;
367}
368
369
370/************\
371* RX Control *
372\************/
373
374/**
375 * ath5k_hw_start_rx_pcu - Start RX engine
376 *
377 * @ah: The &struct ath5k_hw
378 *
379 * Starts RX engine on PCU so that hw can process RXed frames
380 * (ACK etc).
381 *
382 * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
383 * TODO: Init ANI here
384 */
389
390/**
391 * at5k_hw_stop_rx_pcu - Stop RX engine
392 *
393 * @ah: The &struct ath5k_hw
394 *
395 * Stops RX engine on PCU
396 *
397 * TODO: Detach ANI here
398 */
403
404/*
405 * Set multicast filter
406 */
407void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
408{
409 /* Set the multicat filter */
412}
413
414/**
415 * ath5k_hw_get_rx_filter - Get current rx filter
416 *
417 * @ah: The &struct ath5k_hw
418 *
419 * Returns the RX filter by reading rx filter and
420 * phy error filter registers. RX filter is used
421 * to set the allowed frame types that PCU will accept
422 * and pass to the driver. For a list of frame types
423 * check out reg.h.
424 */
426{
427 u32 data, filter = 0;
428
430
431 /*Radar detection for 5212*/
432 if (ah->ah_version == AR5K_AR5212) {
434
439 }
440
441 return filter;
442}
443
444/**
445 * ath5k_hw_set_rx_filter - Set rx filter
446 *
447 * @ah: The &struct ath5k_hw
448 * @filter: RX filter mask (see reg.h)
449 *
450 * Sets RX filter register and also handles PHY error filter
451 * register on 5212 and newer chips so that we have proper PHY
452 * error reporting.
453 */
455{
456 u32 data = 0;
457
458 /* Set PHY error filter register on 5212*/
459 if (ah->ah_version == AR5K_AR5212) {
464 }
465
466 /*
467 * The AR5210 uses promiscous mode to detect radar activity
468 */
469 if (ah->ah_version == AR5K_AR5210 &&
473 }
474
475 /*Zero length DMA (phy error reporting) */
476 if (data)
478 else
480
481 /*Write RX Filter register*/
483
484 /*Write PHY error filter register on 5212*/
485 if (ah->ah_version == AR5K_AR5212)
487
488}
489
490/*********************\
491* Key table functions *
492\*********************/
493
494/*
495 * Reset a key entry on the table
496 */
498{
499 unsigned int i, type;
500 u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
501
503
504 for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
506
507 /* Reset associated MIC entry if TKIP
508 * is enabled located at offset (entry + 64) */
510 for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
512 AR5K_KEYTABLE_OFF(micentry, i));
513 }
514
515 /*
516 * Set NULL encryption on AR5212+
517 *
518 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
519 * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
520 *
521 * Note2: Windows driver (ndiswrapper) sets this to
522 * 0x00000714 instead of 0x00000007
523 */
524 if (ah->ah_version >= AR5K_AR5211) {
526 AR5K_KEYTABLE_TYPE(entry));
527
530 AR5K_KEYTABLE_TYPE(micentry));
531 }
532 }
533
534 return 0;
535}
#define AR5K_BSS_IDM0
Definition reg.h:1645
#define AR5K_RX_FILTER_RADARERR
Definition reg.h:1337
#define AR5K_TIME_OUT
Definition reg.h:1168
#define AR5K_MCAST_FILTER0
Definition reg.h:1346
#define AR5K_RX_FILTER
Definition reg.h:1320
#define AR5K_STA_ID1_ACKCTS_6MB
Definition reg.h:1137
#define AR5K_PHY_ERR_FIL_CCK
Definition reg.h:1711
#define AR5K_KEYTABLE_TYPE(_n)
Definition reg.h:1815
#define AR5K_BSS_IDM1
Definition reg.h:1646
#define AR5K_KEYTABLE_TYPE_TKIP
Definition reg.h:1819
#define AR5K_RX_FILTER_PHYERR
Definition reg.h:1334
#define AR5K_RXCFG
Definition reg.h:198
#define AR5K_KEYTABLE_TYPE_NULL
Definition reg.h:1822
#define AR5K_RX_FILTER_PROM
Definition reg.h:1327
#define AR5K_KEYTABLE_MIC_OFFSET
Definition reg.h:1830
#define AR5K_BCR
Definition reg.h:105
#define AR5K_TIME_OUT_ACK
Definition reg.h:1169
#define AR5K_DIAG_SW_DIS_RX
Definition reg.h:1397
#define AR5K_PHY_ERR_FIL_OFDM
Definition reg.h:1710
#define AR5K_KEYTABLE_OFF(_n, x)
Definition reg.h:1814
#define AR5K_PHY_ERR_FIL_RADAR
Definition reg.h:1709
#define AR5K_TIME_OUT_CTS
Definition reg.h:1171
#define AR5K_DIAG_SW
Definition reg.h:1387
#define AR5K_STA_ID1
Definition reg.h:1123
#define AR5K_BSS_ID0
Definition reg.h:1149
#define AR5K_MCAST_FILTER1
Definition reg.h:1354
#define AR5K_STA_ID1_KEYSRCH_MODE
Definition reg.h:1141
#define AR5K_BSS_ID1
Definition reg.h:1156
#define AR5K_STA_ID0
Definition reg.h:1117
#define AR5K_STA_ID1_NO_PSPOLL
Definition reg.h:1129
#define AR5K_RXCFG_ZLFDMA
Definition reg.h:201
#define AR5K_PHY_ERR_FIL
Definition reg.h:1708
#define AR5K_STA_ID1_ADHOC
Definition reg.h:1126
#define AR5K_BSS_ID1_AID_S
Definition reg.h:1158
#define AR5K_STA_ID1_PWR_SV
Definition reg.h:1127
#define AR5K_STA_ID1_BASE_RATE_11B
Definition reg.h:1138
#define AR5K_STA_ID1_AP
Definition reg.h:1125
static unsigned int ath5k_hw_clocktoh(unsigned int clock, int turbo)
Definition ath5k.h:1208
#define AR5K_LOW_ID(_a)
Definition ath5k.h:154
#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:106
#define AR5K_KEYCACHE_SIZE
Definition ath5k.h:734
#define AR5K_REG_MS(_val, _flags)
Definition ath5k.h:90
static u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
Definition ath5k.h:1216
#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val)
Definition ath5k.h:98
@ AR5K_AR5210
Definition ath5k.h:256
@ AR5K_AR5212
Definition ath5k.h:258
@ AR5K_AR5211
Definition ath5k.h:257
#define AR5K_HIGH_ID(_a)
Definition ath5k.h:158
static void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
Definition ath5k.h:1224
#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:109
static unsigned int ath5k_hw_htoclock(unsigned int usec, int turbo)
Definition ath5k.h:1199
int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
ath5k_hw_set_bssid_mask - filter out bssids we listen
Definition ath5k_pcu.c:349
int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
Definition ath5k_pcu.c:497
u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
ath5k_hw_get_rx_filter - Get current rx filter
Definition ath5k_pcu.c:425
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high)
ath5k_hw_set_ack_bitrate - set bitrate for ACKs
Definition ath5k_pcu.c:96
void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
Definition ath5k_pcu.c:407
int ath5k_hw_set_opmode(struct ath5k_hw *ah)
ath5k_hw_set_opmode - Set PCU operating mode
Definition ath5k_pcu.c:49
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
ath5k_hw_set_lladdr - Set station id
Definition ath5k_pcu.c:201
unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
Definition ath5k_pcu.c:119
int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
Definition ath5k_pcu.c:131
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
ath5k_hw_start_rx_pcu - Start RX engine
Definition ath5k_pcu.c:385
unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
Definition ath5k_pcu.c:148
void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
ath5k_hw_set_rx_filter - Set rx filter
Definition ath5k_pcu.c:454
void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
at5k_hw_stop_rx_pcu - Stop RX engine
Definition ath5k_pcu.c:399
void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
ath5k_hw_get_lladdr - Get station id
Definition ath5k_pcu.c:188
int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
Definition ath5k_pcu.c:160
void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
ath5k_hw_set_associd - Set BSSID for association
Definition ath5k_pcu.c:229
void timeout(int)
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EIO
Input/output error.
Definition errno.h:434
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define ETH_ALEN
Definition if_ether.h:9
#define u8
Definition igbvf_osdep.h:40
void __asmcall int val
Definition setjmp.h:12
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint32_t high
High 32 bits of address.
Definition myson.h:1
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:11
uint8_t ah
Definition registers.h:1
ath5k_hw_get_isr - Get interrupt status
Definition ath5k.h:955
#define u16
Definition vga.h:20
#define u32
Definition vga.h:21