00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ath5k.h"
00028 #include "reg.h"
00029 #include "debug.h"
00030 #include "base.h"
00031
00032
00033
00034
00035
00045 int ath5k_hw_set_opmode(struct ath5k_hw *ah)
00046 {
00047 u32 pcu_reg, beacon_reg, low_id, high_id;
00048
00049
00050
00051 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00052 pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
00053 | AR5K_STA_ID1_KEYSRCH_MODE
00054 | (ah->ah_version == AR5K_AR5210 ?
00055 (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
00056
00057 beacon_reg = 0;
00058
00059 ATH5K_TRACE(ah->ah_sc);
00060
00061
00062 pcu_reg |= AR5K_STA_ID1_NO_KEYSRCH
00063 | (ah->ah_version == AR5K_AR5210 ?
00064 AR5K_STA_ID1_NO_PSPOLL : 0);
00065
00066
00067
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
00076
00077 if (ah->ah_version == AR5K_AR5210)
00078 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
00079
00080 return 0;
00081 }
00082
00093 void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
00094 struct ieee80211_low_level_stats *stats)
00095 {
00096 ATH5K_TRACE(ah->ah_sc);
00097
00098
00099 stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
00100 stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
00101 stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
00102 stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
00103
00104
00105
00106 ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
00107
00108
00109 if (ah->ah_version == AR5K_AR5212) {
00110 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
00111 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
00112 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
00113 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
00114 }
00115
00116
00117 }
00118
00131 void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
00132 {
00133 if (ah->ah_version != AR5K_AR5212)
00134 return;
00135 else {
00136 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
00137 if (high)
00138 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
00139 else
00140 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
00141 }
00142 }
00143
00144
00145
00146
00147
00148
00154 unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
00155 {
00156 ATH5K_TRACE(ah->ah_sc);
00157
00158 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
00159 AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
00160 }
00161
00168 int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
00169 {
00170 ATH5K_TRACE(ah->ah_sc);
00171 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
00172 ah->ah_turbo) <= timeout)
00173 return -EINVAL;
00174
00175 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
00176 ath5k_hw_htoclock(timeout, ah->ah_turbo));
00177
00178 return 0;
00179 }
00180
00186 unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
00187 {
00188 ATH5K_TRACE(ah->ah_sc);
00189 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
00190 AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
00191 }
00192
00199 int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
00200 {
00201 ATH5K_TRACE(ah->ah_sc);
00202 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
00203 ah->ah_turbo) <= timeout)
00204 return -EINVAL;
00205
00206 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
00207 ath5k_hw_htoclock(timeout, ah->ah_turbo));
00208
00209 return 0;
00210 }
00211
00212
00213
00214
00215
00216
00228 void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
00229 {
00230 ATH5K_TRACE(ah->ah_sc);
00231 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
00232 }
00233
00242 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
00243 {
00244 u32 low_id, high_id;
00245 u32 pcu_reg;
00246
00247 ATH5K_TRACE(ah->ah_sc);
00248
00249 memcpy(ah->ah_sta_id, mac, ETH_ALEN);
00250
00251 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00252
00253 low_id = AR5K_LOW_ID(mac);
00254 high_id = AR5K_HIGH_ID(mac);
00255
00256 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
00257 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
00258
00259 return 0;
00260 }
00261
00271 void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
00272 {
00273 u32 low_id, high_id;
00274 u16 tim_offset = 0;
00275
00276
00277
00278
00279 if (ah->ah_version == AR5K_AR5212) {
00280 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
00281 AR5K_BSS_IDM0);
00282 ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
00283 AR5K_BSS_IDM1);
00284 }
00285
00286
00287
00288
00289 low_id = AR5K_LOW_ID(bssid);
00290 high_id = AR5K_HIGH_ID(bssid);
00291 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
00292 ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
00293 AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
00294
00295 if (assoc_id == 0) {
00296 ath5k_hw_disable_pspoll(ah);
00297 return;
00298 }
00299
00300 AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
00301 tim_offset ? tim_offset + 4 : 0);
00302
00303 ath5k_hw_enable_pspoll(ah, NULL, 0);
00304 }
00305
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
00403 {
00404 u32 low_id, high_id;
00405 ATH5K_TRACE(ah->ah_sc);
00406
00407
00408
00409 memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
00410 if (ah->ah_version == AR5K_AR5212) {
00411 low_id = AR5K_LOW_ID(mask);
00412 high_id = AR5K_HIGH_ID(mask);
00413
00414 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
00415 ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
00416
00417 return 0;
00418 }
00419
00420 return -EIO;
00421 }
00422
00423
00424
00425
00426
00427
00439 void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
00440 {
00441 ATH5K_TRACE(ah->ah_sc);
00442 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
00443 }
00444
00454 void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
00455 {
00456 ATH5K_TRACE(ah->ah_sc);
00457 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
00458 }
00459
00460
00461
00462
00463 void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
00464 {
00465 ATH5K_TRACE(ah->ah_sc);
00466
00467 ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
00468 ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
00469 }
00470
00471
00472
00473
00474 int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
00475 {
00476
00477 ATH5K_TRACE(ah->ah_sc);
00478 if (index >= 64)
00479 return -EINVAL;
00480 else if (index >= 32)
00481 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
00482 (1 << (index - 32)));
00483 else
00484 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
00485
00486 return 0;
00487 }
00488
00489
00490
00491
00492 int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
00493 {
00494
00495 ATH5K_TRACE(ah->ah_sc);
00496 if (index >= 64)
00497 return -EINVAL;
00498 else if (index >= 32)
00499 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
00500 (1 << (index - 32)));
00501 else
00502 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
00503
00504 return 0;
00505 }
00506
00518 u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
00519 {
00520 u32 data, filter = 0;
00521
00522 ATH5K_TRACE(ah->ah_sc);
00523 filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
00524
00525
00526 if (ah->ah_version == AR5K_AR5212) {
00527 data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
00528
00529 if (data & AR5K_PHY_ERR_FIL_RADAR)
00530 filter |= AR5K_RX_FILTER_RADARERR;
00531 if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
00532 filter |= AR5K_RX_FILTER_PHYERR;
00533 }
00534
00535 return filter;
00536 }
00537
00548 void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
00549 {
00550 u32 data = 0;
00551
00552 ATH5K_TRACE(ah->ah_sc);
00553
00554
00555 if (ah->ah_version == AR5K_AR5212) {
00556 if (filter & AR5K_RX_FILTER_RADARERR)
00557 data |= AR5K_PHY_ERR_FIL_RADAR;
00558 if (filter & AR5K_RX_FILTER_PHYERR)
00559 data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
00560 }
00561
00562
00563
00564
00565 if (ah->ah_version == AR5K_AR5210 &&
00566 (filter & AR5K_RX_FILTER_RADARERR)) {
00567 filter &= ~AR5K_RX_FILTER_RADARERR;
00568 filter |= AR5K_RX_FILTER_PROM;
00569 }
00570
00571
00572 if (data)
00573 AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00574 else
00575 AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00576
00577
00578 ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
00579
00580
00581 if (ah->ah_version == AR5K_AR5212)
00582 ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
00583
00584 }
00585