iPXE
ath5k_pcu.c File Reference
#include "ath5k.h"
#include "reg.h"
#include "base.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (MIT)
 FILE_SECBOOT (FORBIDDEN)
int ath5k_hw_set_opmode (struct ath5k_hw *ah)
 ath5k_hw_set_opmode - Set PCU operating mode
void ath5k_hw_set_ack_bitrate_high (struct ath5k_hw *ah, int high)
 ath5k_hw_set_ack_bitrate - set bitrate for ACKs
unsigned int ath5k_hw_get_ack_timeout (struct ath5k_hw *ah)
 ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
int ath5k_hw_set_ack_timeout (struct ath5k_hw *ah, unsigned int timeout)
 ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
unsigned int ath5k_hw_get_cts_timeout (struct ath5k_hw *ah)
 ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
int ath5k_hw_set_cts_timeout (struct ath5k_hw *ah, unsigned int timeout)
 ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
void ath5k_hw_get_lladdr (struct ath5k_hw *ah, u8 *mac)
 ath5k_hw_get_lladdr - Get station id
int ath5k_hw_set_lladdr (struct ath5k_hw *ah, const u8 *mac)
 ath5k_hw_set_lladdr - Set station id
void ath5k_hw_set_associd (struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
 ath5k_hw_set_associd - Set BSSID for association
int ath5k_hw_set_bssid_mask (struct ath5k_hw *ah, const u8 *mask)
 ath5k_hw_set_bssid_mask - filter out bssids we listen
void ath5k_hw_start_rx_pcu (struct ath5k_hw *ah)
 ath5k_hw_start_rx_pcu - Start RX engine
void ath5k_hw_stop_rx_pcu (struct ath5k_hw *ah)
 at5k_hw_stop_rx_pcu - Stop RX engine
void ath5k_hw_set_mcast_filter (struct ath5k_hw *ah, u32 filter0, u32 filter1)
u32 ath5k_hw_get_rx_filter (struct ath5k_hw *ah)
 ath5k_hw_get_rx_filter - Get current rx filter
void ath5k_hw_set_rx_filter (struct ath5k_hw *ah, u32 filter)
 ath5k_hw_set_rx_filter - Set rx filter
int ath5k_hw_reset_key (struct ath5k_hw *ah, u16 entry)

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( MIT )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ ath5k_hw_set_opmode()

int ath5k_hw_set_opmode ( struct ath5k_hw * ah)

ath5k_hw_set_opmode - Set PCU operating mode

@ah: The &struct ath5k_hw

Initialize PCU for the various operating modes (AP/STA etc)

For iPXE we always assume STA mode.

Definition at line 49 of file ath5k_pcu.c.

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}
#define AR5K_BCR
Definition reg.h:105
#define AR5K_STA_ID1
Definition reg.h:1123
#define AR5K_STA_ID1_KEYSRCH_MODE
Definition reg.h:1141
#define AR5K_STA_ID0
Definition reg.h:1117
#define AR5K_STA_ID1_NO_PSPOLL
Definition reg.h:1129
#define AR5K_STA_ID1_ADHOC
Definition reg.h:1126
#define AR5K_STA_ID1_PWR_SV
Definition reg.h:1127
#define AR5K_STA_ID1_AP
Definition reg.h:1125
#define AR5K_LOW_ID(_a)
Definition ath5k.h:154
static u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
Definition ath5k.h:1216
@ AR5K_AR5210
Definition ath5k.h:256
#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
uint8_t ah
Definition registers.h:1
#define u32
Definition vga.h:21

References ah, AR5K_AR5210, AR5K_BCR, AR5K_HIGH_ID, AR5K_LOW_ID, AR5K_STA_ID0, AR5K_STA_ID1, AR5K_STA_ID1_ADHOC, AR5K_STA_ID1_AP, AR5K_STA_ID1_KEYSRCH_MODE, AR5K_STA_ID1_NO_PSPOLL, AR5K_STA_ID1_PWR_SV, ath5k_hw_reg_read(), ath5k_hw_reg_write(), and u32.

Referenced by ath5k_hw_attach(), ath5k_hw_reset(), and ath5k_mode_setup().

◆ ath5k_hw_set_ack_bitrate_high()

void ath5k_hw_set_ack_bitrate_high ( struct ath5k_hw * ah,
int high )

ath5k_hw_set_ack_bitrate - set bitrate for ACKs

@ah: The &struct ath5k_hw @high: Flag to determine if we want to use high transmition rate for ACKs or not

If high flag is set, we tell hw to use a set of control rates based on the current transmition rate (check out control_rates array inside reset.c). If not hw just uses the lowest rate available for the current modulation scheme being used (1Mbit for CCK and 6Mbits for OFDM).

Definition at line 96 of file ath5k_pcu.c.

97{
98 if (ah->ah_version != AR5K_AR5212)
99 return;
100 else {
102 if (high)
104 else
106 }
107}
#define AR5K_STA_ID1_ACKCTS_6MB
Definition reg.h:1137
#define AR5K_STA_ID1_BASE_RATE_11B
Definition reg.h:1138
#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:106
@ AR5K_AR5212
Definition ath5k.h:258
#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:109
void __asmcall int val
Definition setjmp.h:12
uint32_t high
High 32 bits of address.
Definition myson.h:1

References ah, AR5K_AR5212, AR5K_REG_DISABLE_BITS, AR5K_REG_ENABLE_BITS, AR5K_STA_ID1, AR5K_STA_ID1_ACKCTS_6MB, AR5K_STA_ID1_BASE_RATE_11B, high, u32, and val.

Referenced by ath5k_init().

◆ ath5k_hw_get_ack_timeout()

unsigned int ath5k_hw_get_ack_timeout ( struct ath5k_hw * ah)

ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec

@ah: The &struct ath5k_hw

Definition at line 119 of file ath5k_pcu.c.

120{
122 AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
123}
#define AR5K_TIME_OUT
Definition reg.h:1168
#define AR5K_TIME_OUT_ACK
Definition reg.h:1169
static unsigned int ath5k_hw_clocktoh(unsigned int clock, int turbo)
Definition ath5k.h:1208
#define AR5K_REG_MS(_val, _flags)
Definition ath5k.h:90

References ah, AR5K_REG_MS, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, ath5k_hw_clocktoh(), and ath5k_hw_reg_read().

◆ ath5k_hw_set_ack_timeout()

int ath5k_hw_set_ack_timeout ( struct ath5k_hw * ah,
unsigned int timeout )

ath5k_hw_set_ack_timeout - Set ACK timeout on PCU

@ah: The &struct ath5k_hw @timeout: Timeout in usec

Definition at line 131 of file ath5k_pcu.c.

132{
134 ah->ah_turbo) <= timeout)
135 return -EINVAL;
136
138 ath5k_hw_htoclock(timeout, ah->ah_turbo));
139
140 return 0;
141}
#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val)
Definition ath5k.h:98
static unsigned int ath5k_hw_htoclock(unsigned int usec, int turbo)
Definition ath5k.h:1199
void timeout(int)
#define EINVAL
Invalid argument.
Definition errno.h:429

References ah, AR5K_REG_MS, AR5K_REG_WRITE_BITS, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, ath5k_hw_clocktoh(), ath5k_hw_htoclock(), EINVAL, and timeout().

◆ ath5k_hw_get_cts_timeout()

unsigned int ath5k_hw_get_cts_timeout ( struct ath5k_hw * ah)

ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec

@ah: The &struct ath5k_hw

Definition at line 148 of file ath5k_pcu.c.

149{
151 AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
152}
#define AR5K_TIME_OUT_CTS
Definition reg.h:1171

References ah, AR5K_REG_MS, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, ath5k_hw_clocktoh(), and ath5k_hw_reg_read().

◆ ath5k_hw_set_cts_timeout()

int ath5k_hw_set_cts_timeout ( struct ath5k_hw * ah,
unsigned int timeout )

ath5k_hw_set_cts_timeout - Set CTS timeout on PCU

@ah: The &struct ath5k_hw @timeout: Timeout in usec

Definition at line 160 of file ath5k_pcu.c.

161{
163 ah->ah_turbo) <= timeout)
164 return -EINVAL;
165
167 ath5k_hw_htoclock(timeout, ah->ah_turbo));
168
169 return 0;
170}

References ah, AR5K_REG_MS, AR5K_REG_WRITE_BITS, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, ath5k_hw_clocktoh(), ath5k_hw_htoclock(), EINVAL, and timeout().

◆ ath5k_hw_get_lladdr()

void ath5k_hw_get_lladdr ( struct ath5k_hw * ah,
u8 * mac )

ath5k_hw_get_lladdr - Get station id

@ah: The &struct ath5k_hw @mac: The card's mac address

Initialize ah->ah_sta_id using the mac address provided (just a memcpy).

TODO: Remove it once we merge ath5k_softc and ath5k_hw

Definition at line 188 of file ath5k_pcu.c.

189{
190 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
191}
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
#define ETH_ALEN
Definition if_ether.h:9
void * memcpy(void *dest, const void *src, size_t len) __nonnull

References ah, ETH_ALEN, mac, memcpy(), and u8.

◆ ath5k_hw_set_lladdr()

int ath5k_hw_set_lladdr ( struct ath5k_hw * ah,
const u8 * mac )

ath5k_hw_set_lladdr - Set station id

@ah: The &struct ath5k_hw @mac: The card's mac address

Set station id on hw using the provided mac address

Definition at line 201 of file ath5k_pcu.c.

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}

References ah, AR5K_HIGH_ID, AR5K_LOW_ID, AR5K_STA_ID0, AR5K_STA_ID1, ath5k_hw_reg_read(), ath5k_hw_reg_write(), ETH_ALEN, mac, memcpy(), u32, and u8.

Referenced by ath5k_start(), and ath5k_stop().

◆ ath5k_hw_set_associd()

void ath5k_hw_set_associd ( struct ath5k_hw * ah,
const u8 * bssid,
u16 assoc_id )

ath5k_hw_set_associd - Set BSSID for association

@ah: The &struct ath5k_hw @bssid: BSSID @assoc_id: Assoc id

Sets the BSSID which trigers the "SME Join" operation

Definition at line 229 of file ath5k_pcu.c.

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}
#define AR5K_BSS_IDM0
Definition reg.h:1645
#define AR5K_BSS_IDM1
Definition reg.h:1646
#define AR5K_BSS_ID0
Definition reg.h:1149
#define AR5K_BSS_ID1
Definition reg.h:1156
#define AR5K_BSS_ID1_AID_S
Definition reg.h:1158

References ah, AR5K_AR5212, AR5K_BSS_ID0, AR5K_BSS_ID1, AR5K_BSS_ID1_AID_S, AR5K_BSS_IDM0, AR5K_BSS_IDM1, AR5K_HIGH_ID, AR5K_LOW_ID, ath5k_hw_reg_write(), u16, u32, and u8.

Referenced by ath5k_config(), ath5k_hw_attach(), and ath5k_hw_reset().

◆ ath5k_hw_set_bssid_mask()

int ath5k_hw_set_bssid_mask ( struct ath5k_hw * ah,
const u8 * mask )

ath5k_hw_set_bssid_mask - filter out bssids we listen

@ah: the &struct ath5k_hw @mask: the bssid_mask, a u8 array of size ETH_ALEN

BSSID masking is a method used by AR5212 and newer hardware to inform PCU which bits of the interface's MAC address should be looked at when trying to decide which packets to ACK. In station mode and AP mode with a single BSS every bit matters since we lock to only one BSS. In AP mode with multiple BSSes (virtual interfaces) not every bit matters because hw must accept frames for all BSSes and so we tweak some bits of our mac address in order to have multiple BSSes.

NOTE: This is a simple filter and does not filter out all relevant frames. Some frames that are not for us might get ACKed from us by PCU because they just match the mask.

When handling multiple BSSes you can get the BSSID mask by computing the set of ~ ( MAC XOR BSSID ) for all bssids we handle.

When you do this you are essentially computing the common bits of all your BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with the MAC address to obtain the relevant bits and compare the result with (frame's BSSID & mask) to see if they match.

Definition at line 349 of file ath5k_pcu.c.

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}
#define EIO
Input/output error.
Definition errno.h:434

References ah, AR5K_AR5212, AR5K_BSS_IDM0, AR5K_BSS_IDM1, AR5K_HIGH_ID, AR5K_LOW_ID, ath5k_hw_reg_write(), EIO, ETH_ALEN, memcpy(), u32, and u8.

Referenced by ath5k_attach(), and ath5k_mode_setup().

◆ ath5k_hw_start_rx_pcu()

void ath5k_hw_start_rx_pcu ( struct ath5k_hw * ah)

ath5k_hw_start_rx_pcu - Start RX engine

@ah: The &struct ath5k_hw

Starts RX engine on PCU so that hw can process RXed frames (ACK etc).

NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma TODO: Init ANI here

Definition at line 385 of file ath5k_pcu.c.

386{
388}
#define AR5K_DIAG_SW_DIS_RX
Definition reg.h:1397
#define AR5K_DIAG_SW
Definition reg.h:1387

References ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX, and AR5K_REG_DISABLE_BITS.

Referenced by ath5k_rx_start().

◆ ath5k_hw_stop_rx_pcu()

void ath5k_hw_stop_rx_pcu ( struct ath5k_hw * ah)

at5k_hw_stop_rx_pcu - Stop RX engine

@ah: The &struct ath5k_hw

Stops RX engine on PCU

TODO: Detach ANI here

Definition at line 399 of file ath5k_pcu.c.

References ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX, and AR5K_REG_ENABLE_BITS.

Referenced by ath5k_rx_stop().

◆ ath5k_hw_set_mcast_filter()

void ath5k_hw_set_mcast_filter ( struct ath5k_hw * ah,
u32 filter0,
u32 filter1 )

Definition at line 407 of file ath5k_pcu.c.

408{
409 /* Set the multicat filter */
412}
#define AR5K_MCAST_FILTER0
Definition reg.h:1346
#define AR5K_MCAST_FILTER1
Definition reg.h:1354

References ah, AR5K_MCAST_FILTER0, AR5K_MCAST_FILTER1, ath5k_hw_reg_write(), and u32.

Referenced by ath5k_configure_filter(), and ath5k_mode_setup().

◆ ath5k_hw_get_rx_filter()

u32 ath5k_hw_get_rx_filter ( struct ath5k_hw * ah)

ath5k_hw_get_rx_filter - Get current rx filter

@ah: The &struct ath5k_hw

Returns the RX filter by reading rx filter and phy error filter registers. RX filter is used to set the allowed frame types that PCU will accept and pass to the driver. For a list of frame types check out reg.h.

Definition at line 425 of file ath5k_pcu.c.

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}
#define AR5K_RX_FILTER_RADARERR
Definition reg.h:1337
#define AR5K_RX_FILTER
Definition reg.h:1320
#define AR5K_PHY_ERR_FIL_CCK
Definition reg.h:1711
#define AR5K_RX_FILTER_PHYERR
Definition reg.h:1334
#define AR5K_PHY_ERR_FIL_OFDM
Definition reg.h:1710
#define AR5K_PHY_ERR_FIL_RADAR
Definition reg.h:1709
#define AR5K_PHY_ERR_FIL
Definition reg.h:1708
uint8_t data[48]
Additional event data.
Definition ena.h:11
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:11

References ah, AR5K_AR5212, AR5K_PHY_ERR_FIL, AR5K_PHY_ERR_FIL_CCK, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHY_ERR_FIL_RADAR, AR5K_RX_FILTER, AR5K_RX_FILTER_PHYERR, AR5K_RX_FILTER_RADARERR, ath5k_hw_reg_read(), data, filter, and u32.

◆ ath5k_hw_set_rx_filter()

void ath5k_hw_set_rx_filter ( struct ath5k_hw * ah,
u32 filter )

ath5k_hw_set_rx_filter - Set rx filter

@ah: The &struct ath5k_hw @filter: RX filter mask (see reg.h)

Sets RX filter register and also handles PHY error filter register on 5212 and newer chips so that we have proper PHY error reporting.

Definition at line 454 of file ath5k_pcu.c.

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}
#define AR5K_RXCFG
Definition reg.h:198
#define AR5K_RX_FILTER_PROM
Definition reg.h:1327
#define AR5K_RXCFG_ZLFDMA
Definition reg.h:201

References ah, AR5K_AR5210, AR5K_AR5212, AR5K_PHY_ERR_FIL, AR5K_PHY_ERR_FIL_CCK, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHY_ERR_FIL_RADAR, AR5K_REG_DISABLE_BITS, AR5K_REG_ENABLE_BITS, AR5K_RX_FILTER, AR5K_RX_FILTER_PHYERR, AR5K_RX_FILTER_PROM, AR5K_RX_FILTER_RADARERR, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA, ath5k_hw_reg_write(), data, filter, and u32.

Referenced by ath5k_configure_filter(), ath5k_mode_setup(), and ath5k_rx_stop().

◆ ath5k_hw_reset_key()

int ath5k_hw_reset_key ( struct ath5k_hw * ah,
u16 entry )

Definition at line 497 of file ath5k_pcu.c.

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_KEYTABLE_TYPE(_n)
Definition reg.h:1815
#define AR5K_KEYTABLE_TYPE_TKIP
Definition reg.h:1819
#define AR5K_KEYTABLE_TYPE_NULL
Definition reg.h:1822
#define AR5K_KEYTABLE_MIC_OFFSET
Definition reg.h:1830
#define AR5K_KEYTABLE_OFF(_n, x)
Definition reg.h:1814
#define AR5K_KEYCACHE_SIZE
Definition ath5k.h:734
@ AR5K_AR5211
Definition ath5k.h:257
uint32_t type
Operating system type.
Definition ena.h:1
#define u16
Definition vga.h:20

References ah, AR5K_AR5211, AR5K_KEYCACHE_SIZE, AR5K_KEYTABLE_MIC_OFFSET, AR5K_KEYTABLE_OFF, AR5K_KEYTABLE_TYPE, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE_TKIP, ath5k_hw_reg_read(), ath5k_hw_reg_write(), type, and u16.

Referenced by ath5k_init().