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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include "ath5k.h"
00059 #include "reg.h"
00060 #include "debug.h"
00061 #include "base.h"
00062
00063
00064
00065
00066
00076 int ath5k_hw_set_opmode(struct ath5k_hw *ah)
00077 {
00078 u32 pcu_reg, beacon_reg, low_id, high_id;
00079
00080
00081
00082 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00083 pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
00084 | AR5K_STA_ID1_KEYSRCH_MODE
00085 | (ah->ah_version == AR5K_AR5210 ?
00086 (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
00087
00088 beacon_reg = 0;
00089
00090 ATH5K_TRACE(ah->ah_sc);
00091
00092
00093 pcu_reg |= AR5K_STA_ID1_NO_KEYSRCH
00094 | (ah->ah_version == AR5K_AR5210 ?
00095 AR5K_STA_ID1_NO_PSPOLL : 0);
00096
00097
00098
00099
00100 low_id = AR5K_LOW_ID(ah->ah_sta_id);
00101 high_id = AR5K_HIGH_ID(ah->ah_sta_id);
00102 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
00103 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
00104
00105
00106
00107
00108 if (ah->ah_version == AR5K_AR5210)
00109 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
00110
00111 return 0;
00112 }
00113
00124 void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
00125 struct ieee80211_low_level_stats *stats)
00126 {
00127 ATH5K_TRACE(ah->ah_sc);
00128
00129
00130 stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
00131 stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
00132 stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
00133 stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
00134
00135
00136
00137 ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
00138
00139
00140 if (ah->ah_version == AR5K_AR5212) {
00141 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
00142 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
00143 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
00144 ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
00145 }
00146
00147
00148 }
00149
00162 void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
00163 {
00164 if (ah->ah_version != AR5K_AR5212)
00165 return;
00166 else {
00167 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
00168 if (high)
00169 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
00170 else
00171 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00185 unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
00186 {
00187 ATH5K_TRACE(ah->ah_sc);
00188
00189 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
00190 AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
00191 }
00192
00199 int ath5k_hw_set_ack_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_ACK),
00203 ah->ah_turbo) <= timeout)
00204 return -EINVAL;
00205
00206 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
00207 ath5k_hw_htoclock(timeout, ah->ah_turbo));
00208
00209 return 0;
00210 }
00211
00217 unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
00218 {
00219 ATH5K_TRACE(ah->ah_sc);
00220 return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
00221 AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
00222 }
00223
00230 int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
00231 {
00232 ATH5K_TRACE(ah->ah_sc);
00233 if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
00234 ah->ah_turbo) <= timeout)
00235 return -EINVAL;
00236
00237 AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
00238 ath5k_hw_htoclock(timeout, ah->ah_turbo));
00239
00240 return 0;
00241 }
00242
00243
00244
00245
00246
00247
00259 void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
00260 {
00261 ATH5K_TRACE(ah->ah_sc);
00262 memcpy(mac, ah->ah_sta_id, ETH_ALEN);
00263 }
00264
00273 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
00274 {
00275 u32 low_id, high_id;
00276 u32 pcu_reg;
00277
00278 ATH5K_TRACE(ah->ah_sc);
00279
00280 memcpy(ah->ah_sta_id, mac, ETH_ALEN);
00281
00282 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
00283
00284 low_id = AR5K_LOW_ID(mac);
00285 high_id = AR5K_HIGH_ID(mac);
00286
00287 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
00288 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
00289
00290 return 0;
00291 }
00292
00302 void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
00303 {
00304 u32 low_id, high_id;
00305 u16 tim_offset = 0;
00306
00307
00308
00309
00310 if (ah->ah_version == AR5K_AR5212) {
00311 ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
00312 AR5K_BSS_IDM0);
00313 ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
00314 AR5K_BSS_IDM1);
00315 }
00316
00317
00318
00319
00320 low_id = AR5K_LOW_ID(bssid);
00321 high_id = AR5K_HIGH_ID(bssid);
00322 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
00323 ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
00324 AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
00325
00326 if (assoc_id == 0) {
00327 ath5k_hw_disable_pspoll(ah);
00328 return;
00329 }
00330
00331 AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
00332 tim_offset ? tim_offset + 4 : 0);
00333
00334 ath5k_hw_enable_pspoll(ah, NULL, 0);
00335 }
00336
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
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
00434 {
00435 u32 low_id, high_id;
00436 ATH5K_TRACE(ah->ah_sc);
00437
00438
00439
00440 memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
00441 if (ah->ah_version == AR5K_AR5212) {
00442 low_id = AR5K_LOW_ID(mask);
00443 high_id = AR5K_HIGH_ID(mask);
00444
00445 ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
00446 ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
00447
00448 return 0;
00449 }
00450
00451 return -EIO;
00452 }
00453
00454
00455
00456
00457
00458
00470 void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
00471 {
00472 ATH5K_TRACE(ah->ah_sc);
00473 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
00474 }
00475
00485 void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
00486 {
00487 ATH5K_TRACE(ah->ah_sc);
00488 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
00489 }
00490
00491
00492
00493
00494 void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
00495 {
00496 ATH5K_TRACE(ah->ah_sc);
00497
00498 ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
00499 ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
00500 }
00501
00502
00503
00504
00505 int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
00506 {
00507
00508 ATH5K_TRACE(ah->ah_sc);
00509 if (index >= 64)
00510 return -EINVAL;
00511 else if (index >= 32)
00512 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
00513 (1 << (index - 32)));
00514 else
00515 AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
00516
00517 return 0;
00518 }
00519
00520
00521
00522
00523 int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
00524 {
00525
00526 ATH5K_TRACE(ah->ah_sc);
00527 if (index >= 64)
00528 return -EINVAL;
00529 else if (index >= 32)
00530 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
00531 (1 << (index - 32)));
00532 else
00533 AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
00534
00535 return 0;
00536 }
00537
00549 u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
00550 {
00551 u32 data, filter = 0;
00552
00553 ATH5K_TRACE(ah->ah_sc);
00554 filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
00555
00556
00557 if (ah->ah_version == AR5K_AR5212) {
00558 data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
00559
00560 if (data & AR5K_PHY_ERR_FIL_RADAR)
00561 filter |= AR5K_RX_FILTER_RADARERR;
00562 if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
00563 filter |= AR5K_RX_FILTER_PHYERR;
00564 }
00565
00566 return filter;
00567 }
00568
00579 void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
00580 {
00581 u32 data = 0;
00582
00583 ATH5K_TRACE(ah->ah_sc);
00584
00585
00586 if (ah->ah_version == AR5K_AR5212) {
00587 if (filter & AR5K_RX_FILTER_RADARERR)
00588 data |= AR5K_PHY_ERR_FIL_RADAR;
00589 if (filter & AR5K_RX_FILTER_PHYERR)
00590 data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
00591 }
00592
00593
00594
00595
00596 if (ah->ah_version == AR5K_AR5210 &&
00597 (filter & AR5K_RX_FILTER_RADARERR)) {
00598 filter &= ~AR5K_RX_FILTER_RADARERR;
00599 filter |= AR5K_RX_FILTER_PROM;
00600 }
00601
00602
00603 if (data)
00604 AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00605 else
00606 AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
00607
00608
00609 ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
00610
00611
00612 if (ah->ah_version == AR5K_AR5212)
00613 ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
00614
00615 }
00616