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