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)
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 ( MIT   ) 

int ath5k_hw_set_opmode ( struct ath5k_hw ah  ) 

ath5k_hw_set_opmode - Set PCU operating mode

: The &struct ath5k_hw

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

For gPXE we always assume STA mode.

Definition at line 48 of file ath5k_pcu.c.

References ath5k_hw::ah_sta_id, ath5k_hw::ah_version, 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().

00049 {
00050         u32 pcu_reg, beacon_reg, low_id, high_id;
00051 
00052 
00053         /* Preserve rest settings */
00054         pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00055         pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
00056                         | AR5K_STA_ID1_KEYSRCH_MODE
00057                         | (ah->ah_version == AR5K_AR5210 ?
00058                         (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
00059 
00060         beacon_reg = 0;
00061 
00062         pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
00063                 | (ah->ah_version == AR5K_AR5210 ?
00064                    AR5K_STA_ID1_PWR_SV : 0);
00065 
00066         /*
00067          * Set PCU registers
00068          */
00069         low_id = AR5K_LOW_ID(ah->ah_sta_id);
00070         high_id = AR5K_HIGH_ID(ah->ah_sta_id);
00071         ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
00072         ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
00073 
00074         /*
00075          * Set Beacon Control Register on 5210
00076          */
00077         if (ah->ah_version == AR5K_AR5210)
00078                 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
00079 
00080         return 0;
00081 }

void ath5k_hw_set_ack_bitrate_high ( struct ath5k_hw ah,
int  high 
)

ath5k_hw_set_ack_bitrate - set bitrate for ACKs

: The &struct ath5k_hw : 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 95 of file ath5k_pcu.c.

References ath5k_hw::ah_version, AR5K_AR5212, AR5K_REG_DISABLE_BITS, AR5K_REG_ENABLE_BITS, AR5K_STA_ID1, AR5K_STA_ID1_ACKCTS_6MB, AR5K_STA_ID1_BASE_RATE_11B, and u32.

Referenced by ath5k_init().

00096 {
00097         if (ah->ah_version != AR5K_AR5212)
00098                 return;
00099         else {
00100                 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
00101                 if (high)
00102                         AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
00103                 else
00104                         AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
00105         }
00106 }

unsigned int ath5k_hw_get_ack_timeout ( struct ath5k_hw ah  ) 

ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec

: The &struct ath5k_hw

Definition at line 118 of file ath5k_pcu.c.

References ath5k_hw::ah_turbo, AR5K_REG_MS, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, ath5k_hw_clocktoh(), and ath5k_hw_reg_read().

int ath5k_hw_set_ack_timeout ( struct ath5k_hw ah,
unsigned int  timeout 
)

ath5k_hw_set_ack_timeout - Set ACK timeout on PCU

: The &struct ath5k_hw : Timeout in usec

Definition at line 130 of file ath5k_pcu.c.

References ath5k_hw::ah_turbo, AR5K_REG_MS, AR5K_REG_WRITE_BITS, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, ath5k_hw_clocktoh(), ath5k_hw_htoclock(), and EINVAL.

00131 {
00132         if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
00133                         ah->ah_turbo) <= timeout)
00134                 return -EINVAL;
00135 
00136         AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
00137                 ath5k_hw_htoclock(timeout, ah->ah_turbo));
00138 
00139         return 0;
00140 }

unsigned int ath5k_hw_get_cts_timeout ( struct ath5k_hw ah  ) 

ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec

: The &struct ath5k_hw

Definition at line 147 of file ath5k_pcu.c.

References ath5k_hw::ah_turbo, AR5K_REG_MS, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, ath5k_hw_clocktoh(), and ath5k_hw_reg_read().

int ath5k_hw_set_cts_timeout ( struct ath5k_hw ah,
unsigned int  timeout 
)

ath5k_hw_set_cts_timeout - Set CTS timeout on PCU

: The &struct ath5k_hw : Timeout in usec

Definition at line 159 of file ath5k_pcu.c.

References ath5k_hw::ah_turbo, AR5K_REG_MS, AR5K_REG_WRITE_BITS, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, ath5k_hw_clocktoh(), ath5k_hw_htoclock(), and EINVAL.

00160 {
00161         if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
00162                         ah->ah_turbo) <= timeout)
00163                 return -EINVAL;
00164 
00165         AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
00166                         ath5k_hw_htoclock(timeout, ah->ah_turbo));
00167 
00168         return 0;
00169 }

void ath5k_hw_get_lladdr ( struct ath5k_hw ah,
u8 mac 
)

ath5k_hw_get_lladdr - Get station id

: The &struct ath5k_hw : 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 187 of file ath5k_pcu.c.

References ath5k_hw::ah_sta_id, ETH_ALEN, and memcpy.

00188 {
00189         memcpy(mac, ah->ah_sta_id, ETH_ALEN);
00190 }

int ath5k_hw_set_lladdr ( struct ath5k_hw ah,
const u8 mac 
)

ath5k_hw_set_lladdr - Set station id

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

Set station id on hw using the provided mac address

Definition at line 200 of file ath5k_pcu.c.

References ath5k_hw::ah_sta_id, AR5K_HIGH_ID, AR5K_LOW_ID, AR5K_STA_ID0, AR5K_STA_ID1, ath5k_hw_reg_read(), ath5k_hw_reg_write(), ETH_ALEN, memcpy, and u32.

Referenced by ath5k_start(), and ath5k_stop().

00201 {
00202         u32 low_id, high_id;
00203         u32 pcu_reg;
00204 
00205         /* Set new station ID */
00206         memcpy(ah->ah_sta_id, mac, ETH_ALEN);
00207 
00208         pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00209 
00210         low_id = AR5K_LOW_ID(mac);
00211         high_id = AR5K_HIGH_ID(mac);
00212 
00213         ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
00214         ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
00215 
00216         return 0;
00217 }

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

ath5k_hw_set_associd - Set BSSID for association

: The &struct ath5k_hw : BSSID : Assoc id

Sets the BSSID which trigers the "SME Join" operation

Definition at line 228 of file ath5k_pcu.c.

References ath5k_hw::ah_bssid_mask, ath5k_hw::ah_version, 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(), and u32.

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

00229 {
00230         u32 low_id, high_id;
00231 
00232         /*
00233          * Set simple BSSID mask on 5212
00234          */
00235         if (ah->ah_version == AR5K_AR5212) {
00236                 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
00237                                                         AR5K_BSS_IDM0);
00238                 ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
00239                                                         AR5K_BSS_IDM1);
00240         }
00241 
00242         /*
00243          * Set BSSID which triggers the "SME Join" operation
00244          */
00245         low_id = AR5K_LOW_ID(bssid);
00246         high_id = AR5K_HIGH_ID(bssid);
00247         ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
00248         ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
00249                                 AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
00250 }

int ath5k_hw_set_bssid_mask ( struct ath5k_hw ah,
const u8 mask 
)

ath5k_hw_set_bssid_mask - filter out bssids we listen

: the &struct ath5k_hw : 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 348 of file ath5k_pcu.c.

References ath5k_hw::ah_bssid_mask, ath5k_hw::ah_version, AR5K_AR5212, AR5K_BSS_IDM0, AR5K_BSS_IDM1, AR5K_HIGH_ID, AR5K_LOW_ID, ath5k_hw_reg_write(), EIO, ETH_ALEN, memcpy, and u32.

Referenced by ath5k_attach(), and ath5k_mode_setup().

00349 {
00350         u32 low_id, high_id;
00351 
00352         /* Cache bssid mask so that we can restore it
00353          * on reset */
00354         memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
00355         if (ah->ah_version == AR5K_AR5212) {
00356                 low_id = AR5K_LOW_ID(mask);
00357                 high_id = AR5K_HIGH_ID(mask);
00358 
00359                 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
00360                 ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
00361 
00362                 return 0;
00363         }
00364 
00365         return -EIO;
00366 }

void ath5k_hw_start_rx_pcu ( struct ath5k_hw ah  ) 

ath5k_hw_start_rx_pcu - Start RX engine

: 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 384 of file ath5k_pcu.c.

References AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX, and AR5K_REG_DISABLE_BITS.

Referenced by ath5k_rx_start().

void ath5k_hw_stop_rx_pcu ( struct ath5k_hw ah  ) 

at5k_hw_stop_rx_pcu - Stop RX engine

: The &struct ath5k_hw

Stops RX engine on PCU

TODO: Detach ANI here

Definition at line 398 of file ath5k_pcu.c.

References AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX, and AR5K_REG_ENABLE_BITS.

Referenced by ath5k_rx_stop().

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

Definition at line 406 of file ath5k_pcu.c.

References AR5K_MCAST_FILTER0, AR5K_MCAST_FILTER1, and ath5k_hw_reg_write().

Referenced by ath5k_configure_filter(), and ath5k_mode_setup().

00407 {
00408         /* Set the multicat filter */
00409         ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
00410         ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
00411 }

u32 ath5k_hw_get_rx_filter ( struct ath5k_hw ah  ) 

ath5k_hw_get_rx_filter - Get current rx filter

: 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 424 of file ath5k_pcu.c.

References ath5k_hw::ah_version, 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(), filter(), and u32.

00425 {
00426         u32 data, filter = 0;
00427 
00428         filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
00429 
00430         /*Radar detection for 5212*/
00431         if (ah->ah_version == AR5K_AR5212) {
00432                 data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
00433 
00434                 if (data & AR5K_PHY_ERR_FIL_RADAR)
00435                         filter |= AR5K_RX_FILTER_RADARERR;
00436                 if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
00437                         filter |= AR5K_RX_FILTER_PHYERR;
00438         }
00439 
00440         return filter;
00441 }

void ath5k_hw_set_rx_filter ( struct ath5k_hw ah,
u32  filter 
)

ath5k_hw_set_rx_filter - Set rx filter

: The &struct ath5k_hw : 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 453 of file ath5k_pcu.c.

References ath5k_hw::ah_version, 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(), and u32.

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

00454 {
00455         u32 data = 0;
00456 
00457         /* Set PHY error filter register on 5212*/
00458         if (ah->ah_version == AR5K_AR5212) {
00459                 if (filter & AR5K_RX_FILTER_RADARERR)
00460                         data |= AR5K_PHY_ERR_FIL_RADAR;
00461                 if (filter & AR5K_RX_FILTER_PHYERR)
00462                         data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
00463         }
00464 
00465         /*
00466          * The AR5210 uses promiscous mode to detect radar activity
00467          */
00468         if (ah->ah_version == AR5K_AR5210 &&
00469                         (filter & AR5K_RX_FILTER_RADARERR)) {
00470                 filter &= ~AR5K_RX_FILTER_RADARERR;
00471                 filter |= AR5K_RX_FILTER_PROM;
00472         }
00473 
00474         /*Zero length DMA (phy error reporting) */
00475         if (data)
00476                 AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00477         else
00478                 AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00479 
00480         /*Write RX Filter register*/
00481         ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
00482 
00483         /*Write PHY error filter register on 5212*/
00484         if (ah->ah_version == AR5K_AR5212)
00485                 ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
00486 
00487 }

int ath5k_hw_reset_key ( struct ath5k_hw ah,
u16  entry 
)

Definition at line 496 of file ath5k_pcu.c.

References ath5k_hw::ah_version, 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(), and u16.

Referenced by ath5k_init().

00497 {
00498         unsigned int i, type;
00499         u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
00500 
00501         type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
00502 
00503         for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
00504                 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
00505 
00506         /* Reset associated MIC entry if TKIP
00507          * is enabled located at offset (entry + 64) */
00508         if (type == AR5K_KEYTABLE_TYPE_TKIP) {
00509                 for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
00510                         ath5k_hw_reg_write(ah, 0,
00511                                 AR5K_KEYTABLE_OFF(micentry, i));
00512         }
00513 
00514         /*
00515          * Set NULL encryption on AR5212+
00516          *
00517          * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
00518          *       AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
00519          *
00520          * Note2: Windows driver (ndiswrapper) sets this to
00521          *        0x00000714 instead of 0x00000007
00522          */
00523         if (ah->ah_version >= AR5K_AR5211) {
00524                 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
00525                                 AR5K_KEYTABLE_TYPE(entry));
00526 
00527                 if (type == AR5K_KEYTABLE_TYPE_TKIP) {
00528                         ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
00529                                 AR5K_KEYTABLE_TYPE(micentry));
00530                 }
00531         }
00532 
00533         return 0;
00534 }


Generated on Tue Apr 6 20:01:20 2010 for gPXE by  doxygen 1.5.7.1