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