00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 FILE_LICENCE ( MIT );
00023
00024
00025
00026
00027
00028 #include "ath5k.h"
00029 #include "reg.h"
00030 #include "base.h"
00031
00032
00033
00034
00035
00036 #define FCS_LEN 4
00037
00038
00039
00040
00041 static int
00042 ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
00043 unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
00044 unsigned int tx_power __unused, unsigned int tx_rate0, unsigned int tx_tries0,
00045 unsigned int key_index __unused, unsigned int antenna_mode, unsigned int flags,
00046 unsigned int rtscts_rate __unused, unsigned int rtscts_duration)
00047 {
00048 u32 frame_type;
00049 struct ath5k_hw_2w_tx_ctl *tx_ctl;
00050 unsigned int frame_len;
00051
00052 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
00053
00054
00055
00056
00057
00058
00059
00060 if (tx_tries0 == 0) {
00061 DBG("ath5k: zero retries\n");
00062 return -EINVAL;
00063 }
00064 if (tx_rate0 == 0) {
00065 DBG("ath5k: zero rate\n");
00066 return -EINVAL;
00067 }
00068
00069
00070 memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
00071
00072
00073
00074
00075
00076 frame_len = pkt_len + FCS_LEN;
00077
00078 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
00079 return -EINVAL;
00080
00081 tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
00082
00083
00084
00085 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
00086 return -EINVAL;
00087
00088 tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
00089
00090
00091
00092
00093
00094 if (ah->ah_version == AR5K_AR5210) {
00095 if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
00096 return -EINVAL;
00097 tx_ctl->tx_control_0 |=
00098 AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
00099 }
00100
00101
00102 if (ah->ah_version == AR5K_AR5210) {
00103 switch (type) {
00104 case AR5K_PKT_TYPE_BEACON:
00105 case AR5K_PKT_TYPE_PROBE_RESP:
00106 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
00107 case AR5K_PKT_TYPE_PIFS:
00108 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
00109 default:
00110 frame_type = type ;
00111 }
00112
00113 tx_ctl->tx_control_0 |=
00114 AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
00115 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
00116
00117 } else {
00118 tx_ctl->tx_control_0 |=
00119 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
00120 AR5K_REG_SM(antenna_mode,
00121 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
00122 tx_ctl->tx_control_1 |=
00123 AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
00124 }
00125 #define _TX_FLAGS(_c, _flag) \
00126 if (flags & AR5K_TXDESC_##_flag) { \
00127 tx_ctl->tx_control_##_c |= \
00128 AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
00129 }
00130
00131 _TX_FLAGS(0, CLRDMASK);
00132 _TX_FLAGS(0, VEOL);
00133 _TX_FLAGS(0, INTREQ);
00134 _TX_FLAGS(0, RTSENA);
00135 _TX_FLAGS(1, NOACK);
00136
00137 #undef _TX_FLAGS
00138
00139
00140
00141
00142 if ((ah->ah_version == AR5K_AR5210) &&
00143 (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
00144 tx_ctl->tx_control_1 |= rtscts_duration &
00145 AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
00146
00147 return 0;
00148 }
00149
00150
00151
00152
00153 static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
00154 struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len __unused,
00155 enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
00156 unsigned int tx_tries0, unsigned int key_index __unused,
00157 unsigned int antenna_mode, unsigned int flags,
00158 unsigned int rtscts_rate,
00159 unsigned int rtscts_duration)
00160 {
00161 struct ath5k_hw_4w_tx_ctl *tx_ctl;
00162 unsigned int frame_len;
00163
00164 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
00165
00166
00167
00168
00169
00170
00171
00172 if (tx_tries0 == 0) {
00173 DBG("ath5k: zero retries\n");
00174 return -EINVAL;
00175 }
00176 if (tx_rate0 == 0) {
00177 DBG("ath5k: zero rate\n");
00178 return -EINVAL;
00179 }
00180
00181 tx_power += ah->ah_txpower.txp_offset;
00182 if (tx_power > AR5K_TUNE_MAX_TXPOWER)
00183 tx_power = AR5K_TUNE_MAX_TXPOWER;
00184
00185
00186 memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
00187
00188
00189
00190
00191
00192 frame_len = pkt_len + FCS_LEN;
00193
00194 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
00195 return -EINVAL;
00196
00197 tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
00198
00199
00200
00201 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
00202 return -EINVAL;
00203
00204 tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
00205
00206 tx_ctl->tx_control_0 |=
00207 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
00208 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
00209 tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
00210 AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
00211 tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
00212 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
00213 tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
00214
00215 #define _TX_FLAGS(_c, _flag) \
00216 if (flags & AR5K_TXDESC_##_flag) { \
00217 tx_ctl->tx_control_##_c |= \
00218 AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
00219 }
00220
00221 _TX_FLAGS(0, CLRDMASK);
00222 _TX_FLAGS(0, VEOL);
00223 _TX_FLAGS(0, INTREQ);
00224 _TX_FLAGS(0, RTSENA);
00225 _TX_FLAGS(0, CTSENA);
00226 _TX_FLAGS(1, NOACK);
00227
00228 #undef _TX_FLAGS
00229
00230
00231
00232
00233 if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
00234 if ((flags & AR5K_TXDESC_RTSENA) &&
00235 (flags & AR5K_TXDESC_CTSENA))
00236 return -EINVAL;
00237 tx_ctl->tx_control_2 |= rtscts_duration &
00238 AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
00239 tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
00240 AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
00241 }
00242
00243 return 0;
00244 }
00245
00246
00247
00248
00249 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah __unused,
00250 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
00251 {
00252 struct ath5k_hw_2w_tx_ctl *tx_ctl;
00253 struct ath5k_hw_tx_status *tx_status;
00254
00255 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
00256 tx_status = &desc->ud.ds_tx5210.tx_stat;
00257
00258
00259 if ((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)
00260 return -EINPROGRESS;
00261
00262
00263
00264
00265 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
00266 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
00267 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
00268 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
00269 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
00270 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
00271
00272 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
00273 AR5K_DESC_TX_STATUS1_SEQ_NUM);
00274 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
00275 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
00276 ts->ts_antenna = 1;
00277 ts->ts_status = 0;
00278 ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
00279 AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
00280 ts->ts_retry[0] = ts->ts_longretry;
00281 ts->ts_final_idx = 0;
00282
00283 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
00284 if (tx_status->tx_status_0 &
00285 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
00286 ts->ts_status |= AR5K_TXERR_XRETRY;
00287
00288 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
00289 ts->ts_status |= AR5K_TXERR_FIFO;
00290
00291 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
00292 ts->ts_status |= AR5K_TXERR_FILT;
00293 }
00294
00295 return 0;
00296 }
00297
00298
00299
00300
00301 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah __unused,
00302 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
00303 {
00304 struct ath5k_hw_4w_tx_ctl *tx_ctl;
00305 struct ath5k_hw_tx_status *tx_status;
00306
00307 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
00308 tx_status = &desc->ud.ds_tx5212.tx_stat;
00309
00310
00311 if (!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))
00312 return -EINPROGRESS;
00313
00314
00315
00316
00317 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
00318 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
00319 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
00320 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
00321 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
00322 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
00323 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
00324 AR5K_DESC_TX_STATUS1_SEQ_NUM);
00325 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
00326 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
00327 ts->ts_antenna = (tx_status->tx_status_1 &
00328 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
00329 ts->ts_status = 0;
00330
00331 ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
00332 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
00333
00334 ts->ts_retry[0] = ts->ts_longretry;
00335 ts->ts_rate[0] = tx_ctl->tx_control_3 &
00336 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
00337
00338
00339 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
00340 if (tx_status->tx_status_0 &
00341 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
00342 ts->ts_status |= AR5K_TXERR_XRETRY;
00343
00344 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
00345 ts->ts_status |= AR5K_TXERR_FIFO;
00346
00347 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
00348 ts->ts_status |= AR5K_TXERR_FILT;
00349 }
00350
00351 return 0;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361 static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah __unused,
00362 struct ath5k_desc *desc,
00363 u32 size, unsigned int flags)
00364 {
00365 struct ath5k_hw_rx_ctl *rx_ctl;
00366
00367 rx_ctl = &desc->ud.ds_rx.rx_ctl;
00368
00369
00370
00371
00372
00373
00374
00375
00376 memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
00377
00378
00379 rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
00380 if (rx_ctl->rx_control_1 != size)
00381 return -EINVAL;
00382
00383 if (flags & AR5K_RXDESC_INTREQ)
00384 rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
00385
00386 return 0;
00387 }
00388
00389
00390
00391
00392 static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah __unused,
00393 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
00394 {
00395 struct ath5k_hw_rx_status *rx_status;
00396
00397 rx_status = &desc->ud.ds_rx.u.rx_stat;
00398
00399
00400 if (!(rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE))
00401 return -EINPROGRESS;
00402
00403
00404
00405
00406 rs->rs_datalen = rx_status->rx_status_0 &
00407 AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
00408 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
00409 AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
00410 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
00411 AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
00412 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
00413 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
00414 rs->rs_more = !!(rx_status->rx_status_0 &
00415 AR5K_5210_RX_DESC_STATUS0_MORE);
00416
00417 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
00418 AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
00419 rs->rs_status = 0;
00420 rs->rs_phyerr = 0;
00421 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
00422
00423
00424
00425
00426 if (!(rx_status->rx_status_1 &
00427 AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
00428 if (rx_status->rx_status_1 &
00429 AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
00430 rs->rs_status |= AR5K_RXERR_CRC;
00431
00432 if (rx_status->rx_status_1 &
00433 AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
00434 rs->rs_status |= AR5K_RXERR_FIFO;
00435
00436 if (rx_status->rx_status_1 &
00437 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
00438 rs->rs_status |= AR5K_RXERR_PHY;
00439 rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
00440 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
00441 }
00442
00443 if (rx_status->rx_status_1 &
00444 AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
00445 rs->rs_status |= AR5K_RXERR_DECRYPT;
00446 }
00447
00448 return 0;
00449 }
00450
00451
00452
00453
00454 static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah __unused,
00455 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
00456 {
00457 struct ath5k_hw_rx_status *rx_status;
00458 struct ath5k_hw_rx_error *rx_err;
00459
00460 rx_status = &desc->ud.ds_rx.u.rx_stat;
00461
00462
00463 rx_err = &desc->ud.ds_rx.u.rx_err;
00464
00465
00466 if (!(rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE))
00467 return -EINPROGRESS;
00468
00469
00470
00471
00472 rs->rs_datalen = rx_status->rx_status_0 &
00473 AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
00474 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
00475 AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
00476 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
00477 AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
00478 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
00479 AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
00480 rs->rs_more = !!(rx_status->rx_status_0 &
00481 AR5K_5212_RX_DESC_STATUS0_MORE);
00482 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
00483 AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
00484 rs->rs_status = 0;
00485 rs->rs_phyerr = 0;
00486 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
00487
00488
00489
00490
00491 if (!(rx_status->rx_status_1 &
00492 AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
00493 if (rx_status->rx_status_1 &
00494 AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
00495 rs->rs_status |= AR5K_RXERR_CRC;
00496
00497 if (rx_status->rx_status_1 &
00498 AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
00499 rs->rs_status |= AR5K_RXERR_PHY;
00500 rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
00501 AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
00502 }
00503
00504 if (rx_status->rx_status_1 &
00505 AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
00506 rs->rs_status |= AR5K_RXERR_DECRYPT;
00507
00508 if (rx_status->rx_status_1 &
00509 AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
00510 rs->rs_status |= AR5K_RXERR_MIC;
00511 }
00512
00513 return 0;
00514 }
00515
00516
00517
00518
00519 int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
00520 {
00521
00522 if (ah->ah_version != AR5K_AR5210 &&
00523 ah->ah_version != AR5K_AR5211 &&
00524 ah->ah_version != AR5K_AR5212)
00525 return -ENOTSUP;
00526
00527 if (ah->ah_version == AR5K_AR5212) {
00528 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
00529 ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
00530 ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
00531 } else {
00532 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
00533 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
00534 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
00535 }
00536
00537 if (ah->ah_version == AR5K_AR5212)
00538 ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
00539 else if (ah->ah_version <= AR5K_AR5211)
00540 ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
00541
00542 return 0;
00543 }
00544