Home | History | Annotate | Download | only in ath5k
      1 /*
      2  * Copyright (c) 2004-2008 Reyk Floeter <reyk (at) openbsd.org>
      3  * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm (at) gmail.com>
      4  * Copyright (c) 2007-2008 Pavel Roskin <proski (at) gnu.org>
      5  *
      6  * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj (at) rwcr.net>.
      7  *
      8  * Permission to use, copy, modify, and distribute this software for any
      9  * purpose with or without fee is hereby granted, provided that the above
     10  * copyright notice and this permission notice appear in all copies.
     11  *
     12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     19  *
     20  */
     21 
     22 FILE_LICENCE ( MIT );
     23 
     24 /******************************\
     25  Hardware Descriptor Functions
     26 \******************************/
     27 
     28 #include "ath5k.h"
     29 #include "reg.h"
     30 #include "base.h"
     31 
     32 /*
     33  * TX Descriptors
     34  */
     35 
     36 #define FCS_LEN	4
     37 
     38 /*
     39  * Initialize the 2-word tx control descriptor on 5210/5211
     40  */
     41 static int
     42 ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
     43 	unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
     44 	unsigned int tx_power __unused, unsigned int tx_rate0, unsigned int tx_tries0,
     45 	unsigned int key_index __unused, unsigned int antenna_mode, unsigned int flags,
     46 	unsigned int rtscts_rate __unused, unsigned int rtscts_duration)
     47 {
     48 	u32 frame_type;
     49 	struct ath5k_hw_2w_tx_ctl *tx_ctl;
     50 	unsigned int frame_len;
     51 
     52 	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
     53 
     54 	/*
     55 	 * Validate input
     56 	 * - Zero retries don't make sense.
     57 	 * - A zero rate will put the HW into a mode where it continously sends
     58 	 *   noise on the channel, so it is important to avoid this.
     59 	 */
     60 	if (tx_tries0 == 0) {
     61 		DBG("ath5k: zero retries\n");
     62 		return -EINVAL;
     63 	}
     64 	if (tx_rate0 == 0) {
     65 		DBG("ath5k: zero rate\n");
     66 		return -EINVAL;
     67 	}
     68 
     69 	/* Clear descriptor */
     70 	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
     71 
     72 	/* Setup control descriptor */
     73 
     74 	/* Verify and set frame length */
     75 
     76 	frame_len = pkt_len + FCS_LEN;
     77 
     78 	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
     79 		return -EINVAL;
     80 
     81 	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
     82 
     83 	/* Verify and set buffer length */
     84 
     85 	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
     86 		return -EINVAL;
     87 
     88 	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
     89 
     90 	/*
     91 	 * Verify and set header length
     92 	 * XXX: I only found that on 5210 code, does it work on 5211 ?
     93 	 */
     94 	if (ah->ah_version == AR5K_AR5210) {
     95 		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
     96 			return -EINVAL;
     97 		tx_ctl->tx_control_0 |=
     98 			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
     99 	}
    100 
    101 	/*Diferences between 5210-5211*/
    102 	if (ah->ah_version == AR5K_AR5210) {
    103 		switch (type) {
    104 		case AR5K_PKT_TYPE_BEACON:
    105 		case AR5K_PKT_TYPE_PROBE_RESP:
    106 			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
    107 		case AR5K_PKT_TYPE_PIFS:
    108 			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
    109 		default:
    110 			frame_type = type /*<< 2 ?*/;
    111 		}
    112 
    113 		tx_ctl->tx_control_0 |=
    114 		AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
    115 		AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
    116 
    117 	} else {
    118 		tx_ctl->tx_control_0 |=
    119 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
    120 			AR5K_REG_SM(antenna_mode,
    121 				AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
    122 		tx_ctl->tx_control_1 |=
    123 			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
    124 	}
    125 #define _TX_FLAGS(_c, _flag)					\
    126 	if (flags & AR5K_TXDESC_##_flag) {			\
    127 		tx_ctl->tx_control_##_c |=			\
    128 			AR5K_2W_TX_DESC_CTL##_c##_##_flag;	\
    129 	}
    130 
    131 	_TX_FLAGS(0, CLRDMASK);
    132 	_TX_FLAGS(0, VEOL);
    133 	_TX_FLAGS(0, INTREQ);
    134 	_TX_FLAGS(0, RTSENA);
    135 	_TX_FLAGS(1, NOACK);
    136 
    137 #undef _TX_FLAGS
    138 
    139 	/*
    140 	 * RTS/CTS Duration [5210 ?]
    141 	 */
    142 	if ((ah->ah_version == AR5K_AR5210) &&
    143 			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
    144 		tx_ctl->tx_control_1 |= rtscts_duration &
    145 				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
    146 
    147 	return 0;
    148 }
    149 
    150 /*
    151  * Initialize the 4-word tx control descriptor on 5212
    152  */
    153 static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
    154 	struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len __unused,
    155 	enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
    156 	unsigned int tx_tries0, unsigned int key_index __unused,
    157 	unsigned int antenna_mode, unsigned int flags,
    158 	unsigned int rtscts_rate,
    159 	unsigned int rtscts_duration)
    160 {
    161 	struct ath5k_hw_4w_tx_ctl *tx_ctl;
    162 	unsigned int frame_len;
    163 
    164 	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
    165 
    166 	/*
    167 	 * Validate input
    168 	 * - Zero retries don't make sense.
    169 	 * - A zero rate will put the HW into a mode where it continously sends
    170 	 *   noise on the channel, so it is important to avoid this.
    171 	 */
    172 	if (tx_tries0 == 0) {
    173 		DBG("ath5k: zero retries\n");
    174 		return -EINVAL;
    175 	}
    176 	if (tx_rate0 == 0) {
    177 		DBG("ath5k: zero rate\n");
    178 		return -EINVAL;
    179 	}
    180 
    181 	tx_power += ah->ah_txpower.txp_offset;
    182 	if (tx_power > AR5K_TUNE_MAX_TXPOWER)
    183 		tx_power = AR5K_TUNE_MAX_TXPOWER;
    184 
    185 	/* Clear descriptor */
    186 	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
    187 
    188 	/* Setup control descriptor */
    189 
    190 	/* Verify and set frame length */
    191 
    192 	frame_len = pkt_len + FCS_LEN;
    193 
    194 	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
    195 		return -EINVAL;
    196 
    197 	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
    198 
    199 	/* Verify and set buffer length */
    200 
    201 	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
    202 		return -EINVAL;
    203 
    204 	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
    205 
    206 	tx_ctl->tx_control_0 |=
    207 		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
    208 		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
    209 	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
    210 					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
    211 	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
    212 					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
    213 	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
    214 
    215 #define _TX_FLAGS(_c, _flag)					\
    216 	if (flags & AR5K_TXDESC_##_flag) {			\
    217 		tx_ctl->tx_control_##_c |=			\
    218 			AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\
    219 	}
    220 
    221 	_TX_FLAGS(0, CLRDMASK);
    222 	_TX_FLAGS(0, VEOL);
    223 	_TX_FLAGS(0, INTREQ);
    224 	_TX_FLAGS(0, RTSENA);
    225 	_TX_FLAGS(0, CTSENA);
    226 	_TX_FLAGS(1, NOACK);
    227 
    228 #undef _TX_FLAGS
    229 
    230 	/*
    231 	 * RTS/CTS
    232 	 */
    233 	if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
    234 		if ((flags & AR5K_TXDESC_RTSENA) &&
    235 				(flags & AR5K_TXDESC_CTSENA))
    236 			return -EINVAL;
    237 		tx_ctl->tx_control_2 |= rtscts_duration &
    238 				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
    239 		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
    240 				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
    241 	}
    242 
    243 	return 0;
    244 }
    245 
    246 /*
    247  * Proccess the tx status descriptor on 5210/5211
    248  */
    249 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah __unused,
    250 		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
    251 {
    252 	struct ath5k_hw_2w_tx_ctl *tx_ctl;
    253 	struct ath5k_hw_tx_status *tx_status;
    254 
    255 	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
    256 	tx_status = &desc->ud.ds_tx5210.tx_stat;
    257 
    258 	/* No frame has been send or error */
    259 	if ((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)
    260 		return -EINPROGRESS;
    261 
    262 	/*
    263 	 * Get descriptor status
    264 	 */
    265 	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
    266 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
    267 	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
    268 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
    269 	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
    270 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
    271 	/*TODO: ts->ts_virtcol + test*/
    272 	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
    273 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
    274 	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
    275 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
    276 	ts->ts_antenna = 1;
    277 	ts->ts_status = 0;
    278 	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
    279 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
    280 	ts->ts_retry[0] = ts->ts_longretry;
    281 	ts->ts_final_idx = 0;
    282 
    283 	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
    284 		if (tx_status->tx_status_0 &
    285 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
    286 			ts->ts_status |= AR5K_TXERR_XRETRY;
    287 
    288 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
    289 			ts->ts_status |= AR5K_TXERR_FIFO;
    290 
    291 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
    292 			ts->ts_status |= AR5K_TXERR_FILT;
    293 	}
    294 
    295 	return 0;
    296 }
    297 
    298 /*
    299  * Proccess a tx status descriptor on 5212
    300  */
    301 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah __unused,
    302 		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
    303 {
    304 	struct ath5k_hw_4w_tx_ctl *tx_ctl;
    305 	struct ath5k_hw_tx_status *tx_status;
    306 
    307 	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
    308 	tx_status = &desc->ud.ds_tx5212.tx_stat;
    309 
    310 	/* No frame has been send or error */
    311 	if (!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))
    312 		return -EINPROGRESS;
    313 
    314 	/*
    315 	 * Get descriptor status
    316 	 */
    317 	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
    318 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
    319 	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
    320 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
    321 	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
    322 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
    323 	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
    324 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
    325 	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
    326 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
    327 	ts->ts_antenna = (tx_status->tx_status_1 &
    328 		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
    329 	ts->ts_status = 0;
    330 
    331 	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
    332 			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
    333 
    334 	ts->ts_retry[0] = ts->ts_longretry;
    335 	ts->ts_rate[0] = tx_ctl->tx_control_3 &
    336 		AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
    337 
    338 	/* TX error */
    339 	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
    340 		if (tx_status->tx_status_0 &
    341 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
    342 			ts->ts_status |= AR5K_TXERR_XRETRY;
    343 
    344 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
    345 			ts->ts_status |= AR5K_TXERR_FIFO;
    346 
    347 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
    348 			ts->ts_status |= AR5K_TXERR_FILT;
    349 	}
    350 
    351 	return 0;
    352 }
    353 
    354 /*
    355  * RX Descriptors
    356  */
    357 
    358 /*
    359  * Initialize an rx control descriptor
    360  */
    361 static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah __unused,
    362 				  struct ath5k_desc *desc,
    363 				  u32 size, unsigned int flags)
    364 {
    365 	struct ath5k_hw_rx_ctl *rx_ctl;
    366 
    367 	rx_ctl = &desc->ud.ds_rx.rx_ctl;
    368 
    369 	/*
    370 	 * Clear the descriptor
    371 	 * If we don't clean the status descriptor,
    372 	 * while scanning we get too many results,
    373 	 * most of them virtual, after some secs
    374 	 * of scanning system hangs. M.F.
    375 	*/
    376 	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
    377 
    378 	/* Setup descriptor */
    379 	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
    380 	if (rx_ctl->rx_control_1 != size)
    381 		return -EINVAL;
    382 
    383 	if (flags & AR5K_RXDESC_INTREQ)
    384 		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
    385 
    386 	return 0;
    387 }
    388 
    389 /*
    390  * Proccess the rx status descriptor on 5210/5211
    391  */
    392 static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah __unused,
    393 		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
    394 {
    395 	struct ath5k_hw_rx_status *rx_status;
    396 
    397 	rx_status = &desc->ud.ds_rx.u.rx_stat;
    398 
    399 	/* No frame received / not ready */
    400 	if (!(rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE))
    401 		return -EINPROGRESS;
    402 
    403 	/*
    404 	 * Frame receive status
    405 	 */
    406 	rs->rs_datalen = rx_status->rx_status_0 &
    407 		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
    408 	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
    409 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
    410 	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
    411 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
    412 	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
    413 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
    414 	rs->rs_more = !!(rx_status->rx_status_0 &
    415 		AR5K_5210_RX_DESC_STATUS0_MORE);
    416 	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
    417 	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
    418 		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
    419 	rs->rs_status = 0;
    420 	rs->rs_phyerr = 0;
    421 	rs->rs_keyix = AR5K_RXKEYIX_INVALID;
    422 
    423 	/*
    424 	 * Receive/descriptor errors
    425 	 */
    426 	if (!(rx_status->rx_status_1 &
    427 	      AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
    428 		if (rx_status->rx_status_1 &
    429 				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
    430 			rs->rs_status |= AR5K_RXERR_CRC;
    431 
    432 		if (rx_status->rx_status_1 &
    433 				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
    434 			rs->rs_status |= AR5K_RXERR_FIFO;
    435 
    436 		if (rx_status->rx_status_1 &
    437 				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
    438 			rs->rs_status |= AR5K_RXERR_PHY;
    439 			rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
    440 				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
    441 		}
    442 
    443 		if (rx_status->rx_status_1 &
    444 				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
    445 			rs->rs_status |= AR5K_RXERR_DECRYPT;
    446 	}
    447 
    448 	return 0;
    449 }
    450 
    451 /*
    452  * Proccess the rx status descriptor on 5212
    453  */
    454 static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah __unused,
    455 		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
    456 {
    457 	struct ath5k_hw_rx_status *rx_status;
    458 	struct ath5k_hw_rx_error *rx_err;
    459 
    460 	rx_status = &desc->ud.ds_rx.u.rx_stat;
    461 
    462 	/* Overlay on error */
    463 	rx_err = &desc->ud.ds_rx.u.rx_err;
    464 
    465 	/* No frame received / not ready */
    466 	if (!(rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE))
    467 		return -EINPROGRESS;
    468 
    469 	/*
    470 	 * Frame receive status
    471 	 */
    472 	rs->rs_datalen = rx_status->rx_status_0 &
    473 		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
    474 	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
    475 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
    476 	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
    477 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
    478 	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
    479 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
    480 	rs->rs_more = !!(rx_status->rx_status_0 &
    481 		AR5K_5212_RX_DESC_STATUS0_MORE);
    482 	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
    483 		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
    484 	rs->rs_status = 0;
    485 	rs->rs_phyerr = 0;
    486 	rs->rs_keyix = AR5K_RXKEYIX_INVALID;
    487 
    488 	/*
    489 	 * Receive/descriptor errors
    490 	 */
    491 	if (!(rx_status->rx_status_1 &
    492 	      AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
    493 		if (rx_status->rx_status_1 &
    494 				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
    495 			rs->rs_status |= AR5K_RXERR_CRC;
    496 
    497 		if (rx_status->rx_status_1 &
    498 				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
    499 			rs->rs_status |= AR5K_RXERR_PHY;
    500 			rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
    501 					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
    502 		}
    503 
    504 		if (rx_status->rx_status_1 &
    505 				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
    506 			rs->rs_status |= AR5K_RXERR_DECRYPT;
    507 
    508 		if (rx_status->rx_status_1 &
    509 				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
    510 			rs->rs_status |= AR5K_RXERR_MIC;
    511 	}
    512 
    513 	return 0;
    514 }
    515 
    516 /*
    517  * Init function pointers inside ath5k_hw struct
    518  */
    519 int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
    520 {
    521 
    522 	if (ah->ah_version != AR5K_AR5210 &&
    523 	    ah->ah_version != AR5K_AR5211 &&
    524 	    ah->ah_version != AR5K_AR5212)
    525 		return -ENOTSUP;
    526 
    527 	if (ah->ah_version == AR5K_AR5212) {
    528 		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
    529 		ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
    530 		ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
    531 	} else {
    532 		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
    533 		ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
    534 		ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
    535 	}
    536 
    537 	if (ah->ah_version == AR5K_AR5212)
    538 		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
    539 	else if (ah->ah_version <= AR5K_AR5211)
    540 		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
    541 
    542 	return 0;
    543 }
    544 
    545