00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ath5k.h"
00025 #include "reg.h"
00026 #include "debug.h"
00027 #include "base.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036 static int
00037 ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
00038 unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
00039 unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
00040 unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
00041 unsigned int rtscts_rate, unsigned int rtscts_duration)
00042 {
00043 u32 frame_type;
00044 struct ath5k_hw_2w_tx_ctl *tx_ctl;
00045 unsigned int frame_len;
00046
00047 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
00048
00049
00050
00051
00052
00053
00054
00055 if (unlikely(tx_tries0 == 0)) {
00056 ATH5K_ERR(ah->ah_sc, "zero retries\n");
00057 WARN_ON(1);
00058 return -EINVAL;
00059 }
00060 if (unlikely(tx_rate0 == 0)) {
00061 ATH5K_ERR(ah->ah_sc, "zero rate\n");
00062 WARN_ON(1);
00063 return -EINVAL;
00064 }
00065
00066
00067 memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
00068
00069
00070
00071
00072
00073
00074 frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
00075
00076 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
00077 return -EINVAL;
00078
00079 tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
00080
00081
00082
00083
00084 if (type == AR5K_PKT_TYPE_BEACON)
00085 pkt_len = roundup(pkt_len, 4);
00086
00087 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
00088 return -EINVAL;
00089
00090 tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
00091
00092
00093
00094
00095
00096 if (ah->ah_version == AR5K_AR5210) {
00097 if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
00098 return -EINVAL;
00099 tx_ctl->tx_control_0 |=
00100 AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
00101 }
00102
00103
00104 if (ah->ah_version == AR5K_AR5210) {
00105 switch (type) {
00106 case AR5K_PKT_TYPE_BEACON:
00107 case AR5K_PKT_TYPE_PROBE_RESP:
00108 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
00109 case AR5K_PKT_TYPE_PIFS:
00110 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
00111 default:
00112 frame_type = type ;
00113 }
00114
00115 tx_ctl->tx_control_0 |=
00116 AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
00117 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
00118
00119 } else {
00120 tx_ctl->tx_control_0 |=
00121 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
00122 AR5K_REG_SM(antenna_mode,
00123 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
00124 tx_ctl->tx_control_1 |=
00125 AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
00126 }
00127 #define _TX_FLAGS(_c, _flag) \
00128 if (flags & AR5K_TXDESC_##_flag) { \
00129 tx_ctl->tx_control_##_c |= \
00130 AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
00131 }
00132
00133 _TX_FLAGS(0, CLRDMASK);
00134 _TX_FLAGS(0, VEOL);
00135 _TX_FLAGS(0, INTREQ);
00136 _TX_FLAGS(0, RTSENA);
00137 _TX_FLAGS(1, NOACK);
00138
00139 #undef _TX_FLAGS
00140
00141
00142
00143
00144 if (key_index != AR5K_TXKEYIX_INVALID) {
00145 tx_ctl->tx_control_0 |=
00146 AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
00147 tx_ctl->tx_control_1 |=
00148 AR5K_REG_SM(key_index,
00149 AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
00150 }
00151
00152
00153
00154
00155 if ((ah->ah_version == AR5K_AR5210) &&
00156 (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
00157 tx_ctl->tx_control_1 |= rtscts_duration &
00158 AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
00159
00160 return 0;
00161 }
00162
00163
00164
00165
00166 static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
00167 struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
00168 enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
00169 unsigned int tx_tries0, unsigned int key_index,
00170 unsigned int antenna_mode, unsigned int flags,
00171 unsigned int rtscts_rate,
00172 unsigned int rtscts_duration)
00173 {
00174 struct ath5k_hw_4w_tx_ctl *tx_ctl;
00175 unsigned int frame_len;
00176
00177 ATH5K_TRACE(ah->ah_sc);
00178 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
00179
00180
00181
00182
00183
00184
00185
00186 if (unlikely(tx_tries0 == 0)) {
00187 ATH5K_ERR(ah->ah_sc, "zero retries\n");
00188 WARN_ON(1);
00189 return -EINVAL;
00190 }
00191 if (unlikely(tx_rate0 == 0)) {
00192 ATH5K_ERR(ah->ah_sc, "zero rate\n");
00193 WARN_ON(1);
00194 return -EINVAL;
00195 }
00196
00197 tx_power += ah->ah_txpower.txp_offset;
00198 if (tx_power > AR5K_TUNE_MAX_TXPOWER)
00199 tx_power = AR5K_TUNE_MAX_TXPOWER;
00200
00201
00202 memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
00203
00204
00205
00206
00207
00208
00209 frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
00210
00211 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
00212 return -EINVAL;
00213
00214 tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
00215
00216
00217
00218
00219 if (type == AR5K_PKT_TYPE_BEACON)
00220 pkt_len = roundup(pkt_len, 4);
00221
00222 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
00223 return -EINVAL;
00224
00225 tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
00226
00227 tx_ctl->tx_control_0 |=
00228 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
00229 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
00230 tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
00231 AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
00232 tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
00233 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
00234 tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
00235
00236 #define _TX_FLAGS(_c, _flag) \
00237 if (flags & AR5K_TXDESC_##_flag) { \
00238 tx_ctl->tx_control_##_c |= \
00239 AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
00240 }
00241
00242 _TX_FLAGS(0, CLRDMASK);
00243 _TX_FLAGS(0, VEOL);
00244 _TX_FLAGS(0, INTREQ);
00245 _TX_FLAGS(0, RTSENA);
00246 _TX_FLAGS(0, CTSENA);
00247 _TX_FLAGS(1, NOACK);
00248
00249 #undef _TX_FLAGS
00250
00251
00252
00253
00254 if (key_index != AR5K_TXKEYIX_INVALID) {
00255 tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
00256 tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
00257 AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
00258 }
00259
00260
00261
00262
00263 if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
00264 if ((flags & AR5K_TXDESC_RTSENA) &&
00265 (flags & AR5K_TXDESC_CTSENA))
00266 return -EINVAL;
00267 tx_ctl->tx_control_2 |= rtscts_duration &
00268 AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
00269 tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
00270 AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
00271 }
00272
00273 return 0;
00274 }
00275
00276
00277
00278
00279 static int
00280 ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
00281 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
00282 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
00283 {
00284 struct ath5k_hw_4w_tx_ctl *tx_ctl;
00285
00286
00287
00288
00289
00290
00291
00292 if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
00293 (tx_rate2 == 0 && tx_tries2 != 0) ||
00294 (tx_rate3 == 0 && tx_tries3 != 0))) {
00295 ATH5K_ERR(ah->ah_sc, "zero rate\n");
00296 WARN_ON(1);
00297 return -EINVAL;
00298 }
00299
00300 if (ah->ah_version == AR5K_AR5212) {
00301 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
00302
00303 #define _XTX_TRIES(_n) \
00304 if (tx_tries##_n) { \
00305 tx_ctl->tx_control_2 |= \
00306 AR5K_REG_SM(tx_tries##_n, \
00307 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
00308 tx_ctl->tx_control_3 |= \
00309 AR5K_REG_SM(tx_rate##_n, \
00310 AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
00311 }
00312
00313 _XTX_TRIES(1);
00314 _XTX_TRIES(2);
00315 _XTX_TRIES(3);
00316
00317 #undef _XTX_TRIES
00318
00319 return 1;
00320 }
00321
00322 return 0;
00323 }
00324
00325
00326 static int
00327 ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
00328 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
00329 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
00330 {
00331 return 0;
00332 }
00333
00334
00335
00336
00337 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
00338 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
00339 {
00340 struct ath5k_hw_2w_tx_ctl *tx_ctl;
00341 struct ath5k_hw_tx_status *tx_status;
00342
00343 ATH5K_TRACE(ah->ah_sc);
00344
00345 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
00346 tx_status = &desc->ud.ds_tx5210.tx_stat;
00347
00348
00349 if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
00350 return -EINPROGRESS;
00351
00352
00353
00354
00355 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
00356 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
00357 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
00358 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
00359 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
00360 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
00361
00362 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
00363 AR5K_DESC_TX_STATUS1_SEQ_NUM);
00364 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
00365 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
00366 ts->ts_antenna = 1;
00367 ts->ts_status = 0;
00368 ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
00369 AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
00370 ts->ts_retry[0] = ts->ts_longretry;
00371 ts->ts_final_idx = 0;
00372
00373 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
00374 if (tx_status->tx_status_0 &
00375 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
00376 ts->ts_status |= AR5K_TXERR_XRETRY;
00377
00378 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
00379 ts->ts_status |= AR5K_TXERR_FIFO;
00380
00381 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
00382 ts->ts_status |= AR5K_TXERR_FILT;
00383 }
00384
00385 return 0;
00386 }
00387
00388
00389
00390
00391 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
00392 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
00393 {
00394 struct ath5k_hw_4w_tx_ctl *tx_ctl;
00395 struct ath5k_hw_tx_status *tx_status;
00396
00397 ATH5K_TRACE(ah->ah_sc);
00398
00399 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
00400 tx_status = &desc->ud.ds_tx5212.tx_stat;
00401
00402
00403 if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
00404 return -EINPROGRESS;
00405
00406
00407
00408
00409 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
00410 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
00411 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
00412 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
00413 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
00414 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
00415 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
00416 AR5K_DESC_TX_STATUS1_SEQ_NUM);
00417 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
00418 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
00419 ts->ts_antenna = (tx_status->tx_status_1 &
00420 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
00421 ts->ts_status = 0;
00422
00423 ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
00424 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
00425
00426
00427
00428
00429
00430
00431 ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
00432 switch (ts->ts_final_idx) {
00433 case 3:
00434 ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
00435 AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
00436
00437 ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
00438 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
00439 ts->ts_longretry += ts->ts_retry[2];
00440
00441 case 2:
00442 ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
00443 AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
00444
00445 ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
00446 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
00447 ts->ts_longretry += ts->ts_retry[1];
00448
00449 case 1:
00450 ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
00451 AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
00452
00453 ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
00454 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
00455 ts->ts_longretry += ts->ts_retry[0];
00456
00457 case 0:
00458 ts->ts_rate[0] = tx_ctl->tx_control_3 &
00459 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
00460 break;
00461 }
00462
00463
00464 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
00465 if (tx_status->tx_status_0 &
00466 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
00467 ts->ts_status |= AR5K_TXERR_XRETRY;
00468
00469 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
00470 ts->ts_status |= AR5K_TXERR_FIFO;
00471
00472 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
00473 ts->ts_status |= AR5K_TXERR_FILT;
00474 }
00475
00476 return 0;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486 static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
00487 u32 size, unsigned int flags)
00488 {
00489 struct ath5k_hw_rx_ctl *rx_ctl;
00490
00491 ATH5K_TRACE(ah->ah_sc);
00492 rx_ctl = &desc->ud.ds_rx.rx_ctl;
00493
00494
00495
00496
00497
00498
00499
00500
00501 memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
00502
00503
00504 rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
00505 if (unlikely(rx_ctl->rx_control_1 != size))
00506 return -EINVAL;
00507
00508 if (flags & AR5K_RXDESC_INTREQ)
00509 rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
00510
00511 return 0;
00512 }
00513
00514
00515
00516
00517 static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
00518 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
00519 {
00520 struct ath5k_hw_rx_status *rx_status;
00521
00522 rx_status = &desc->ud.ds_rx.u.rx_stat;
00523
00524
00525 if (unlikely(!(rx_status->rx_status_1 &
00526 AR5K_5210_RX_DESC_STATUS1_DONE)))
00527 return -EINPROGRESS;
00528
00529
00530
00531
00532 rs->rs_datalen = rx_status->rx_status_0 &
00533 AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
00534 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
00535 AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
00536 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
00537 AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
00538 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
00539 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
00540 rs->rs_more = !!(rx_status->rx_status_0 &
00541 AR5K_5210_RX_DESC_STATUS0_MORE);
00542
00543 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
00544 AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
00545 rs->rs_status = 0;
00546 rs->rs_phyerr = 0;
00547
00548
00549
00550
00551 if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
00552 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
00553 AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
00554 else
00555 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
00556
00557
00558
00559
00560 if (!(rx_status->rx_status_1 &
00561 AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
00562 if (rx_status->rx_status_1 &
00563 AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
00564 rs->rs_status |= AR5K_RXERR_CRC;
00565
00566 if (rx_status->rx_status_1 &
00567 AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
00568 rs->rs_status |= AR5K_RXERR_FIFO;
00569
00570 if (rx_status->rx_status_1 &
00571 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
00572 rs->rs_status |= AR5K_RXERR_PHY;
00573 rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
00574 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
00575 }
00576
00577 if (rx_status->rx_status_1 &
00578 AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
00579 rs->rs_status |= AR5K_RXERR_DECRYPT;
00580 }
00581
00582 return 0;
00583 }
00584
00585
00586
00587
00588 static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
00589 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
00590 {
00591 struct ath5k_hw_rx_status *rx_status;
00592 struct ath5k_hw_rx_error *rx_err;
00593
00594 ATH5K_TRACE(ah->ah_sc);
00595 rx_status = &desc->ud.ds_rx.u.rx_stat;
00596
00597
00598 rx_err = &desc->ud.ds_rx.u.rx_err;
00599
00600
00601 if (unlikely(!(rx_status->rx_status_1 &
00602 AR5K_5212_RX_DESC_STATUS1_DONE)))
00603 return -EINPROGRESS;
00604
00605
00606
00607
00608 rs->rs_datalen = rx_status->rx_status_0 &
00609 AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
00610 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
00611 AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
00612 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
00613 AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
00614 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
00615 AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
00616 rs->rs_more = !!(rx_status->rx_status_0 &
00617 AR5K_5212_RX_DESC_STATUS0_MORE);
00618 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
00619 AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
00620 rs->rs_status = 0;
00621 rs->rs_phyerr = 0;
00622
00623
00624
00625
00626 if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
00627 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
00628 AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
00629 else
00630 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
00631
00632
00633
00634
00635 if (!(rx_status->rx_status_1 &
00636 AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
00637 if (rx_status->rx_status_1 &
00638 AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
00639 rs->rs_status |= AR5K_RXERR_CRC;
00640
00641 if (rx_status->rx_status_1 &
00642 AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
00643 rs->rs_status |= AR5K_RXERR_PHY;
00644 rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
00645 AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
00646 }
00647
00648 if (rx_status->rx_status_1 &
00649 AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
00650 rs->rs_status |= AR5K_RXERR_DECRYPT;
00651
00652 if (rx_status->rx_status_1 &
00653 AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
00654 rs->rs_status |= AR5K_RXERR_MIC;
00655 }
00656
00657 return 0;
00658 }
00659
00660
00661
00662
00663 int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
00664 {
00665
00666 if (ah->ah_version != AR5K_AR5210 &&
00667 ah->ah_version != AR5K_AR5211 &&
00668 ah->ah_version != AR5K_AR5212)
00669 return -ENOTSUPP;
00670
00671
00672 if (ah->ah_version == AR5K_AR5212)
00673 ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
00674 else if (ah->ah_version == AR5K_AR5211)
00675 ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
00676
00677 if (ah->ah_version == AR5K_AR5212) {
00678 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
00679 ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
00680 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
00681 ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
00682 } else {
00683 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
00684 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
00685 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
00686 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
00687 }
00688
00689 if (ah->ah_version == AR5K_AR5212)
00690 ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
00691 else if (ah->ah_version <= AR5K_AR5211)
00692 ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
00693
00694 return 0;
00695 }
00696