1 /* 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2004 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $FreeBSD$ 18 */ 19 #include "opt_ah.h" 20 21 #include "ah.h" 22 #include "ah_internal.h" 23 #include "ah_desc.h" 24 25 #include "ar5210/ar5210.h" 26 #include "ar5210/ar5210reg.h" 27 #include "ar5210/ar5210phy.h" 28 #include "ar5210/ar5210desc.h" 29 30 /* 31 * Set the properties of the tx queue with the parameters 32 * from qInfo. The queue must previously have been setup 33 * with a call to ar5210SetupTxQueue. 34 */ 35 HAL_BOOL 36 ar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) 37 { 38 struct ath_hal_5210 *ahp = AH5210(ah); 39 40 if (q >= HAL_NUM_TX_QUEUES) { 41 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 42 __func__, q); 43 return AH_FALSE; 44 } 45 return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); 46 } 47 48 /* 49 * Return the properties for the specified tx queue. 50 */ 51 HAL_BOOL 52 ar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) 53 { 54 struct ath_hal_5210 *ahp = AH5210(ah); 55 56 if (q >= HAL_NUM_TX_QUEUES) { 57 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 58 __func__, q); 59 return AH_FALSE; 60 } 61 return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); 62 } 63 64 /* 65 * Allocate and initialize a tx DCU/QCU combination. 66 */ 67 int 68 ar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, 69 const HAL_TXQ_INFO *qInfo) 70 { 71 struct ath_hal_5210 *ahp = AH5210(ah); 72 HAL_TX_QUEUE_INFO *qi; 73 int q; 74 75 switch (type) { 76 case HAL_TX_QUEUE_BEACON: 77 q = 2; 78 break; 79 case HAL_TX_QUEUE_CAB: 80 q = 1; 81 break; 82 case HAL_TX_QUEUE_DATA: 83 q = 0; 84 break; 85 default: 86 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", 87 __func__, type); 88 return -1; 89 } 90 91 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 92 93 qi = &ahp->ah_txq[q]; 94 if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { 95 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", 96 __func__, q); 97 return -1; 98 } 99 OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); 100 qi->tqi_type = type; 101 if (qInfo == AH_NULL) { 102 /* by default enable OK+ERR+DESC+URN interrupts */ 103 qi->tqi_qflags = 104 HAL_TXQ_TXOKINT_ENABLE 105 | HAL_TXQ_TXERRINT_ENABLE 106 | HAL_TXQ_TXDESCINT_ENABLE 107 | HAL_TXQ_TXURNINT_ENABLE 108 ; 109 qi->tqi_aifs = INIT_AIFS; 110 qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ 111 qi->tqi_shretry = INIT_SH_RETRY; 112 qi->tqi_lgretry = INIT_LG_RETRY; 113 } else 114 (void) ar5210SetTxQueueProps(ah, q, qInfo); 115 /* NB: must be followed by ar5210ResetTxQueue */ 116 return q; 117 } 118 119 /* 120 * Free a tx DCU/QCU combination. 121 */ 122 HAL_BOOL 123 ar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) 124 { 125 struct ath_hal_5210 *ahp = AH5210(ah); 126 HAL_TX_QUEUE_INFO *qi; 127 128 if (q >= HAL_NUM_TX_QUEUES) { 129 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 130 __func__, q); 131 return AH_FALSE; 132 } 133 qi = &ahp->ah_txq[q]; 134 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 135 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 136 __func__, q); 137 return AH_FALSE; 138 } 139 140 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); 141 142 qi->tqi_type = HAL_TX_QUEUE_INACTIVE; 143 ahp->ah_txOkInterruptMask &= ~(1 << q); 144 ahp->ah_txErrInterruptMask &= ~(1 << q); 145 ahp->ah_txDescInterruptMask &= ~(1 << q); 146 ahp->ah_txEolInterruptMask &= ~(1 << q); 147 ahp->ah_txUrnInterruptMask &= ~(1 << q); 148 149 return AH_TRUE; 150 #undef N 151 } 152 153 HAL_BOOL 154 ar5210ResetTxQueue(struct ath_hal *ah, u_int q) 155 { 156 struct ath_hal_5210 *ahp = AH5210(ah); 157 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 158 HAL_TX_QUEUE_INFO *qi; 159 uint32_t cwMin; 160 161 if (q >= HAL_NUM_TX_QUEUES) { 162 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 163 __func__, q); 164 return AH_FALSE; 165 } 166 qi = &ahp->ah_txq[q]; 167 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 168 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 169 __func__, q); 170 return AH_FALSE; 171 } 172 173 /* 174 * Ignore any non-data queue(s). 175 */ 176 if (qi->tqi_type != HAL_TX_QUEUE_DATA) 177 return AH_TRUE; 178 179 /* Set turbo mode / base mode parameters on or off */ 180 if (IEEE80211_IS_CHAN_TURBO(chan)) { 181 OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); 182 OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); 183 OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); 184 OS_REG_WRITE(ah, AR_IFS0, 185 ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) 186 << AR_IFS0_DIFS_S) 187 | INIT_SIFS_TURBO); 188 OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); 189 OS_REG_WRITE(ah, AR_PHY(17), 190 (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); 191 OS_REG_WRITE(ah, AR_PHY_FRCTL, 192 AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 193 AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 194 AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 195 0x2020 | 196 AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); 197 } else { 198 OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); 199 OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); 200 OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); 201 OS_REG_WRITE(ah, AR_IFS0, 202 ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) 203 << AR_IFS0_DIFS_S) 204 | INIT_SIFS); 205 OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); 206 OS_REG_WRITE(ah, AR_PHY(17), 207 (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); 208 OS_REG_WRITE(ah, AR_PHY_FRCTL, 209 AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 210 AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 211 AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); 212 } 213 214 if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) 215 cwMin = INIT_CWMIN; 216 else 217 cwMin = qi->tqi_cwmin; 218 219 /* Set cwmin and retry limit values */ 220 OS_REG_WRITE(ah, AR_RETRY_LMT, 221 (cwMin << AR_RETRY_LMT_CW_MIN_S) 222 | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) 223 | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) 224 | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) 225 | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) 226 ); 227 228 if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) 229 ahp->ah_txOkInterruptMask |= 1 << q; 230 else 231 ahp->ah_txOkInterruptMask &= ~(1 << q); 232 if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) 233 ahp->ah_txErrInterruptMask |= 1 << q; 234 else 235 ahp->ah_txErrInterruptMask &= ~(1 << q); 236 if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) 237 ahp->ah_txDescInterruptMask |= 1 << q; 238 else 239 ahp->ah_txDescInterruptMask &= ~(1 << q); 240 if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) 241 ahp->ah_txEolInterruptMask |= 1 << q; 242 else 243 ahp->ah_txEolInterruptMask &= ~(1 << q); 244 if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) 245 ahp->ah_txUrnInterruptMask |= 1 << q; 246 else 247 ahp->ah_txUrnInterruptMask &= ~(1 << q); 248 249 return AH_TRUE; 250 } 251 252 /* 253 * Get the TXDP for the "main" data queue. Needs to be extended 254 * for multiple Q functionality 255 */ 256 uint32_t 257 ar5210GetTxDP(struct ath_hal *ah, u_int q) 258 { 259 struct ath_hal_5210 *ahp = AH5210(ah); 260 HAL_TX_QUEUE_INFO *qi; 261 262 HALASSERT(q < HAL_NUM_TX_QUEUES); 263 264 qi = &ahp->ah_txq[q]; 265 switch (qi->tqi_type) { 266 case HAL_TX_QUEUE_DATA: 267 return OS_REG_READ(ah, AR_TXDP0); 268 case HAL_TX_QUEUE_INACTIVE: 269 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 270 __func__, q); 271 /* fall thru... */ 272 default: 273 break; 274 } 275 return 0xffffffff; 276 } 277 278 /* 279 * Set the TxDP for the "main" data queue. 280 */ 281 HAL_BOOL 282 ar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) 283 { 284 struct ath_hal_5210 *ahp = AH5210(ah); 285 HAL_TX_QUEUE_INFO *qi; 286 287 HALASSERT(q < HAL_NUM_TX_QUEUES); 288 289 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", 290 __func__, q, txdp); 291 qi = &ahp->ah_txq[q]; 292 switch (qi->tqi_type) { 293 case HAL_TX_QUEUE_DATA: 294 #ifdef AH_DEBUG 295 /* 296 * Make sure that TXE is deasserted before setting the 297 * TXDP. If TXE is still asserted, setting TXDP will 298 * have no effect. 299 */ 300 if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) 301 ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", 302 __func__, OS_REG_READ(ah, AR_CR)); 303 #endif 304 OS_REG_WRITE(ah, AR_TXDP0, txdp); 305 break; 306 case HAL_TX_QUEUE_BEACON: 307 case HAL_TX_QUEUE_CAB: 308 OS_REG_WRITE(ah, AR_TXDP1, txdp); 309 break; 310 case HAL_TX_QUEUE_INACTIVE: 311 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 312 __func__, q); 313 /* fall thru... */ 314 default: 315 return AH_FALSE; 316 } 317 return AH_TRUE; 318 } 319 320 /* 321 * Update Tx FIFO trigger level. 322 * 323 * Set bIncTrigLevel to TRUE to increase the trigger level. 324 * Set bIncTrigLevel to FALSE to decrease the trigger level. 325 * 326 * Returns TRUE if the trigger level was updated 327 */ 328 HAL_BOOL 329 ar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) 330 { 331 uint32_t curTrigLevel; 332 HAL_INT ints = ar5210GetInterrupts(ah); 333 334 /* 335 * Disable chip interrupts. This is because halUpdateTxTrigLevel 336 * is called from both ISR and non-ISR contexts. 337 */ 338 (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); 339 curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); 340 if (bIncTrigLevel){ 341 /* increase the trigger level */ 342 curTrigLevel = curTrigLevel + 343 ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); 344 } else { 345 /* decrease the trigger level if not already at the minimum */ 346 if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { 347 /* decrease the trigger level */ 348 curTrigLevel--; 349 } else { 350 /* no update to the trigger level */ 351 /* re-enable chip interrupts */ 352 ar5210SetInterrupts(ah, ints); 353 return AH_FALSE; 354 } 355 } 356 /* Update the trigger level */ 357 OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel); 358 /* re-enable chip interrupts */ 359 ar5210SetInterrupts(ah, ints); 360 return AH_TRUE; 361 } 362 363 /* 364 * Set Transmit Enable bits for the specified queues. 365 */ 366 HAL_BOOL 367 ar5210StartTxDma(struct ath_hal *ah, u_int q) 368 { 369 struct ath_hal_5210 *ahp = AH5210(ah); 370 HAL_TX_QUEUE_INFO *qi; 371 372 HALASSERT(q < HAL_NUM_TX_QUEUES); 373 374 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 375 qi = &ahp->ah_txq[q]; 376 switch (qi->tqi_type) { 377 case HAL_TX_QUEUE_DATA: 378 OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0); 379 break; 380 case HAL_TX_QUEUE_CAB: 381 OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1); /* enable altq xmit */ 382 OS_REG_WRITE(ah, AR_BCR, 383 AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV); 384 break; 385 case HAL_TX_QUEUE_BEACON: 386 /* XXX add CR_BCR_BCMD if IBSS mode */ 387 OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE); 388 break; 389 case HAL_TX_QUEUE_INACTIVE: 390 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 391 __func__, q); 392 /* fal thru... */ 393 default: 394 return AH_FALSE; 395 } 396 return AH_TRUE; 397 } 398 399 uint32_t 400 ar5210NumTxPending(struct ath_hal *ah, u_int q) 401 { 402 struct ath_hal_5210 *ahp = AH5210(ah); 403 HAL_TX_QUEUE_INFO *qi; 404 uint32_t v; 405 406 HALASSERT(q < HAL_NUM_TX_QUEUES); 407 408 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 409 qi = &ahp->ah_txq[q]; 410 switch (qi->tqi_type) { 411 case HAL_TX_QUEUE_DATA: 412 v = OS_REG_READ(ah, AR_CFG); 413 return MS(v, AR_CFG_TXCNT); 414 case HAL_TX_QUEUE_INACTIVE: 415 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 416 __func__, q); 417 /* fall thru... */ 418 default: 419 break; 420 } 421 return 0; 422 } 423 424 /* 425 * Stop transmit on the specified queue 426 */ 427 HAL_BOOL 428 ar5210StopTxDma(struct ath_hal *ah, u_int q) 429 { 430 struct ath_hal_5210 *ahp = AH5210(ah); 431 HAL_TX_QUEUE_INFO *qi; 432 433 HALASSERT(q < HAL_NUM_TX_QUEUES); 434 435 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 436 qi = &ahp->ah_txq[q]; 437 switch (qi->tqi_type) { 438 case HAL_TX_QUEUE_DATA: { 439 int i; 440 OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0); 441 for (i = 0; i < 1000; i++) { 442 if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0) 443 break; 444 OS_DELAY(10); 445 } 446 OS_REG_WRITE(ah, AR_CR, 0); 447 return (i < 1000); 448 } 449 case HAL_TX_QUEUE_BEACON: 450 return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0); 451 case HAL_TX_QUEUE_INACTIVE: 452 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 453 __func__, q); 454 /* fall thru... */ 455 default: 456 break; 457 } 458 return AH_FALSE; 459 } 460 461 /* 462 * Descriptor Access Functions 463 */ 464 465 #define VALID_PKT_TYPES \ 466 ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\ 467 (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\ 468 (1<<HAL_PKT_TYPE_BEACON)) 469 #define isValidPktType(_t) ((1<<(_t)) & VALID_PKT_TYPES) 470 #define VALID_TX_RATES \ 471 ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\ 472 (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\ 473 (1<<0x1d)|(1<<0x18)|(1<<0x1c)) 474 #define isValidTxRate(_r) ((1<<(_r)) & VALID_TX_RATES) 475 476 HAL_BOOL 477 ar5210SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, 478 u_int pktLen, 479 u_int hdrLen, 480 HAL_PKT_TYPE type, 481 u_int txPower, 482 u_int txRate0, u_int txTries0, 483 u_int keyIx, 484 u_int antMode, 485 u_int flags, 486 u_int rtsctsRate, 487 u_int rtsctsDuration, 488 u_int compicvLen, 489 u_int compivLen, 490 u_int comp) 491 { 492 struct ar5210_desc *ads = AR5210DESC(ds); 493 uint32_t frtype; 494 495 (void) txPower; 496 (void) rtsctsDuration; 497 498 HALASSERT(txTries0 != 0); 499 HALASSERT(isValidPktType(type)); 500 HALASSERT(isValidTxRate(txRate0)); 501 502 if (type == HAL_PKT_TYPE_BEACON || type == HAL_PKT_TYPE_PROBE_RESP) 503 frtype = AR_Frm_NoDelay; 504 else 505 frtype = type << 26; 506 ads->ds_ctl0 = (pktLen & AR_FrameLen) 507 | (txRate0 << AR_XmitRate_S) 508 | ((hdrLen << AR_HdrLen_S) & AR_HdrLen) 509 | frtype 510 | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) 511 | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) 512 | (antMode ? AR_AntModeXmit : 0) 513 ; 514 if (keyIx != HAL_TXKEYIX_INVALID) { 515 ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; 516 ads->ds_ctl0 |= AR_EncryptKeyValid; 517 } else 518 ads->ds_ctl1 = 0; 519 if (flags & HAL_TXDESC_RTSENA) { 520 ads->ds_ctl0 |= AR_RTSCTSEnable; 521 ads->ds_ctl1 |= (rtsctsDuration << AR_RTSDuration_S) 522 & AR_RTSDuration; 523 } 524 return AH_TRUE; 525 } 526 527 HAL_BOOL 528 ar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, 529 u_int txRate1, u_int txTries1, 530 u_int txRate2, u_int txTries2, 531 u_int txRate3, u_int txTries3) 532 { 533 (void) ah; (void) ds; 534 (void) txRate1; (void) txTries1; 535 (void) txRate2; (void) txTries2; 536 (void) txRate3; (void) txTries3; 537 return AH_FALSE; 538 } 539 540 void 541 ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) 542 { 543 struct ar5210_desc *ads = AR5210DESC(ds); 544 545 ads->ds_ctl0 |= AR_TxInterReq; 546 } 547 548 HAL_BOOL 549 ar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, 550 HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, 551 u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, 552 const struct ath_desc *ds0) 553 { 554 struct ar5210_desc *ads = AR5210DESC(ds); 555 uint32_t segLen = segLenList[0]; 556 557 HALASSERT((segLen &~ AR_BufLen) == 0); 558 559 ds->ds_data = bufAddrList[0]; 560 561 if (firstSeg) { 562 /* 563 * First descriptor, don't clobber xmit control data 564 * setup by ar5210SetupTxDesc. 565 */ 566 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); 567 } else if (lastSeg) { /* !firstSeg && lastSeg */ 568 /* 569 * Last descriptor in a multi-descriptor frame, 570 * copy the transmit parameters from the first 571 * frame for processing on completion. 572 */ 573 ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; 574 ads->ds_ctl1 = segLen; 575 } else { /* !firstSeg && !lastSeg */ 576 /* 577 * Intermediate descriptor in a multi-descriptor frame. 578 */ 579 ads->ds_ctl0 = 0; 580 ads->ds_ctl1 = segLen | AR_More; 581 } 582 ads->ds_status0 = ads->ds_status1 = 0; 583 return AH_TRUE; 584 } 585 586 /* 587 * Processing of HW TX descriptor. 588 */ 589 HAL_STATUS 590 ar5210ProcTxDesc(struct ath_hal *ah, 591 struct ath_desc *ds, struct ath_tx_status *ts) 592 { 593 struct ar5210_desc *ads = AR5210DESC(ds); 594 595 if ((ads->ds_status1 & AR_Done) == 0) 596 return HAL_EINPROGRESS; 597 598 /* Update software copies of the HW status */ 599 ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; 600 ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); 601 ts->ts_status = 0; 602 if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { 603 if (ads->ds_status0 & AR_ExcessiveRetries) 604 ts->ts_status |= HAL_TXERR_XRETRY; 605 if (ads->ds_status0 & AR_Filtered) 606 ts->ts_status |= HAL_TXERR_FILT; 607 if (ads->ds_status0 & AR_FIFOUnderrun) 608 ts->ts_status |= HAL_TXERR_FIFO; 609 } 610 ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); 611 ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); 612 ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); 613 ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); 614 ts->ts_antenna = 0; /* NB: don't know */ 615 ts->ts_finaltsi = 0; 616 617 return HAL_OK; 618 } 619 620 /* 621 * Determine which tx queues need interrupt servicing. 622 * STUB. 623 */ 624 void 625 ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) 626 { 627 return; 628 } 629 630 /* 631 * Retrieve the rate table from the given TX completion descriptor 632 */ 633 HAL_BOOL 634 ar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) 635 { 636 return AH_FALSE; 637 } 638 639 /* 640 * Set the TX descriptor link pointer 641 */ 642 void 643 ar5210SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) 644 { 645 struct ar5210_desc *ads = AR5210DESC(ds); 646 647 ads->ds_link = link; 648 } 649 650 /* 651 * Get the TX descriptor link pointer 652 */ 653 void 654 ar5210GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) 655 { 656 struct ar5210_desc *ads = AR5210DESC(ds); 657 658 *link = ads->ds_link; 659 } 660 661 /* 662 * Get a pointer to the TX descriptor link pointer 663 */ 664 void 665 ar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) 666 { 667 struct ar5210_desc *ads = AR5210DESC(ds); 668 669 *linkptr = &ads->ds_link; 670 } 671