1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2004 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17187831Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_desc.h" 24185377Ssam 25185377Ssam#include "ar5210/ar5210.h" 26185377Ssam#include "ar5210/ar5210reg.h" 27185377Ssam#include "ar5210/ar5210phy.h" 28185377Ssam#include "ar5210/ar5210desc.h" 29185377Ssam 30185377Ssam/* 31185377Ssam * Set the properties of the tx queue with the parameters 32185377Ssam * from qInfo. The queue must previously have been setup 33185377Ssam * with a call to ar5210SetupTxQueue. 34185377Ssam */ 35185377SsamHAL_BOOL 36185377Ssamar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) 37185377Ssam{ 38185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 39185377Ssam 40185377Ssam if (q >= HAL_NUM_TX_QUEUES) { 41185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 42185377Ssam __func__, q); 43185377Ssam return AH_FALSE; 44185377Ssam } 45185377Ssam return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); 46185377Ssam} 47185377Ssam 48185377Ssam/* 49185377Ssam * Return the properties for the specified tx queue. 50185377Ssam */ 51185377SsamHAL_BOOL 52185377Ssamar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) 53185377Ssam{ 54185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 55185377Ssam 56185377Ssam if (q >= HAL_NUM_TX_QUEUES) { 57185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 58185377Ssam __func__, q); 59185377Ssam return AH_FALSE; 60185377Ssam } 61185377Ssam return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); 62185377Ssam} 63185377Ssam 64185377Ssam/* 65185377Ssam * Allocate and initialize a tx DCU/QCU combination. 66185377Ssam */ 67185377Ssamint 68185377Ssamar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, 69185377Ssam const HAL_TXQ_INFO *qInfo) 70185377Ssam{ 71185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 72185377Ssam HAL_TX_QUEUE_INFO *qi; 73185377Ssam int q; 74185377Ssam 75185377Ssam switch (type) { 76185377Ssam case HAL_TX_QUEUE_BEACON: 77185377Ssam q = 2; 78185377Ssam break; 79185377Ssam case HAL_TX_QUEUE_CAB: 80185377Ssam q = 1; 81185377Ssam break; 82185377Ssam case HAL_TX_QUEUE_DATA: 83185377Ssam q = 0; 84185377Ssam break; 85185377Ssam default: 86185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", 87185377Ssam __func__, type); 88185377Ssam return -1; 89185377Ssam } 90185377Ssam 91185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 92185377Ssam 93185377Ssam qi = &ahp->ah_txq[q]; 94185377Ssam if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { 95185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", 96185377Ssam __func__, q); 97185377Ssam return -1; 98185377Ssam } 99185377Ssam OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); 100185377Ssam qi->tqi_type = type; 101185377Ssam if (qInfo == AH_NULL) { 102185377Ssam /* by default enable OK+ERR+DESC+URN interrupts */ 103185377Ssam qi->tqi_qflags = 104185377Ssam HAL_TXQ_TXOKINT_ENABLE 105185377Ssam | HAL_TXQ_TXERRINT_ENABLE 106185377Ssam | HAL_TXQ_TXDESCINT_ENABLE 107185377Ssam | HAL_TXQ_TXURNINT_ENABLE 108185377Ssam ; 109185377Ssam qi->tqi_aifs = INIT_AIFS; 110185377Ssam qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ 111185377Ssam qi->tqi_shretry = INIT_SH_RETRY; 112185377Ssam qi->tqi_lgretry = INIT_LG_RETRY; 113185377Ssam } else 114185377Ssam (void) ar5210SetTxQueueProps(ah, q, qInfo); 115185377Ssam /* NB: must be followed by ar5210ResetTxQueue */ 116185377Ssam return q; 117185377Ssam} 118185377Ssam 119185377Ssam/* 120185377Ssam * Free a tx DCU/QCU combination. 121185377Ssam */ 122185377SsamHAL_BOOL 123185377Ssamar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) 124185377Ssam{ 125185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 126185377Ssam HAL_TX_QUEUE_INFO *qi; 127185377Ssam 128185377Ssam if (q >= HAL_NUM_TX_QUEUES) { 129185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 130185377Ssam __func__, q); 131185377Ssam return AH_FALSE; 132185377Ssam } 133185377Ssam qi = &ahp->ah_txq[q]; 134185377Ssam if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 135185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 136185377Ssam __func__, q); 137185377Ssam return AH_FALSE; 138185377Ssam } 139185377Ssam 140185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); 141185377Ssam 142185377Ssam qi->tqi_type = HAL_TX_QUEUE_INACTIVE; 143185377Ssam ahp->ah_txOkInterruptMask &= ~(1 << q); 144185377Ssam ahp->ah_txErrInterruptMask &= ~(1 << q); 145185377Ssam ahp->ah_txDescInterruptMask &= ~(1 << q); 146185377Ssam ahp->ah_txEolInterruptMask &= ~(1 << q); 147185377Ssam ahp->ah_txUrnInterruptMask &= ~(1 << q); 148185377Ssam 149185377Ssam return AH_TRUE; 150185377Ssam#undef N 151185377Ssam} 152185377Ssam 153185377SsamHAL_BOOL 154185377Ssamar5210ResetTxQueue(struct ath_hal *ah, u_int q) 155185377Ssam{ 156185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 157187831Ssam const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 158185377Ssam HAL_TX_QUEUE_INFO *qi; 159185377Ssam uint32_t cwMin; 160185377Ssam 161185377Ssam if (q >= HAL_NUM_TX_QUEUES) { 162185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 163185377Ssam __func__, q); 164185377Ssam return AH_FALSE; 165185377Ssam } 166185377Ssam qi = &ahp->ah_txq[q]; 167185377Ssam if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 168185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 169185377Ssam __func__, q); 170185377Ssam return AH_FALSE; 171185377Ssam } 172185377Ssam 173185377Ssam /* 174185377Ssam * Ignore any non-data queue(s). 175185377Ssam */ 176185377Ssam if (qi->tqi_type != HAL_TX_QUEUE_DATA) 177185377Ssam return AH_TRUE; 178185377Ssam 179185377Ssam /* Set turbo mode / base mode parameters on or off */ 180187831Ssam if (IEEE80211_IS_CHAN_TURBO(chan)) { 181185377Ssam OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); 182185377Ssam OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); 183185377Ssam OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); 184185377Ssam OS_REG_WRITE(ah, AR_IFS0, 185185377Ssam ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) 186185377Ssam << AR_IFS0_DIFS_S) 187185377Ssam | INIT_SIFS_TURBO); 188185377Ssam OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); 189185377Ssam OS_REG_WRITE(ah, AR_PHY(17), 190185377Ssam (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); 191185377Ssam OS_REG_WRITE(ah, AR_PHY_FRCTL, 192185377Ssam AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 193185377Ssam AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 194185377Ssam AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 195185377Ssam 0x2020 | 196185377Ssam AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); 197185377Ssam } else { 198185377Ssam OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); 199185377Ssam OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); 200185377Ssam OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); 201185377Ssam OS_REG_WRITE(ah, AR_IFS0, 202185377Ssam ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) 203185377Ssam << AR_IFS0_DIFS_S) 204185377Ssam | INIT_SIFS); 205185377Ssam OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); 206185377Ssam OS_REG_WRITE(ah, AR_PHY(17), 207185377Ssam (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); 208185377Ssam OS_REG_WRITE(ah, AR_PHY_FRCTL, 209185377Ssam AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 210185377Ssam AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 211185377Ssam AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); 212185377Ssam } 213185377Ssam 214185377Ssam if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) 215185377Ssam cwMin = INIT_CWMIN; 216185377Ssam else 217185377Ssam cwMin = qi->tqi_cwmin; 218185377Ssam 219185377Ssam /* Set cwmin and retry limit values */ 220185377Ssam OS_REG_WRITE(ah, AR_RETRY_LMT, 221185377Ssam (cwMin << AR_RETRY_LMT_CW_MIN_S) 222185377Ssam | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) 223185377Ssam | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) 224185377Ssam | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) 225185377Ssam | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) 226185377Ssam ); 227185377Ssam 228185377Ssam if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) 229185377Ssam ahp->ah_txOkInterruptMask |= 1 << q; 230185377Ssam else 231185377Ssam ahp->ah_txOkInterruptMask &= ~(1 << q); 232185377Ssam if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) 233185377Ssam ahp->ah_txErrInterruptMask |= 1 << q; 234185377Ssam else 235185377Ssam ahp->ah_txErrInterruptMask &= ~(1 << q); 236185377Ssam if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) 237185377Ssam ahp->ah_txDescInterruptMask |= 1 << q; 238185377Ssam else 239185377Ssam ahp->ah_txDescInterruptMask &= ~(1 << q); 240185377Ssam if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) 241185377Ssam ahp->ah_txEolInterruptMask |= 1 << q; 242185377Ssam else 243185377Ssam ahp->ah_txEolInterruptMask &= ~(1 << q); 244185377Ssam if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) 245185377Ssam ahp->ah_txUrnInterruptMask |= 1 << q; 246185377Ssam else 247185377Ssam ahp->ah_txUrnInterruptMask &= ~(1 << q); 248185377Ssam 249185377Ssam return AH_TRUE; 250185377Ssam} 251185377Ssam 252185377Ssam/* 253185377Ssam * Get the TXDP for the "main" data queue. Needs to be extended 254185377Ssam * for multiple Q functionality 255185377Ssam */ 256185377Ssamuint32_t 257185377Ssamar5210GetTxDP(struct ath_hal *ah, u_int q) 258185377Ssam{ 259185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 260185377Ssam HAL_TX_QUEUE_INFO *qi; 261185377Ssam 262185377Ssam HALASSERT(q < HAL_NUM_TX_QUEUES); 263185377Ssam 264185377Ssam qi = &ahp->ah_txq[q]; 265185377Ssam switch (qi->tqi_type) { 266185377Ssam case HAL_TX_QUEUE_DATA: 267185377Ssam return OS_REG_READ(ah, AR_TXDP0); 268185377Ssam case HAL_TX_QUEUE_INACTIVE: 269185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 270185377Ssam __func__, q); 271185377Ssam /* fall thru... */ 272185377Ssam default: 273185377Ssam break; 274185377Ssam } 275185377Ssam return 0xffffffff; 276185377Ssam} 277185377Ssam 278185377Ssam/* 279185377Ssam * Set the TxDP for the "main" data queue. 280185377Ssam */ 281185377SsamHAL_BOOL 282185377Ssamar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) 283185377Ssam{ 284185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 285185377Ssam HAL_TX_QUEUE_INFO *qi; 286185377Ssam 287185377Ssam HALASSERT(q < HAL_NUM_TX_QUEUES); 288185377Ssam 289185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", 290185377Ssam __func__, q, txdp); 291185377Ssam qi = &ahp->ah_txq[q]; 292185377Ssam switch (qi->tqi_type) { 293185377Ssam case HAL_TX_QUEUE_DATA: 294185377Ssam#ifdef AH_DEBUG 295185377Ssam /* 296185377Ssam * Make sure that TXE is deasserted before setting the 297185377Ssam * TXDP. If TXE is still asserted, setting TXDP will 298185377Ssam * have no effect. 299185377Ssam */ 300185377Ssam if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) 301185377Ssam ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", 302185377Ssam __func__, OS_REG_READ(ah, AR_CR)); 303185377Ssam#endif 304185377Ssam OS_REG_WRITE(ah, AR_TXDP0, txdp); 305185377Ssam break; 306185377Ssam case HAL_TX_QUEUE_BEACON: 307185377Ssam case HAL_TX_QUEUE_CAB: 308185377Ssam OS_REG_WRITE(ah, AR_TXDP1, txdp); 309185377Ssam break; 310185377Ssam case HAL_TX_QUEUE_INACTIVE: 311185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 312185377Ssam __func__, q); 313185377Ssam /* fall thru... */ 314185377Ssam default: 315185377Ssam return AH_FALSE; 316185377Ssam } 317185377Ssam return AH_TRUE; 318185377Ssam} 319185377Ssam 320185377Ssam/* 321185377Ssam * Update Tx FIFO trigger level. 322185377Ssam * 323185377Ssam * Set bIncTrigLevel to TRUE to increase the trigger level. 324185377Ssam * Set bIncTrigLevel to FALSE to decrease the trigger level. 325185377Ssam * 326185377Ssam * Returns TRUE if the trigger level was updated 327185377Ssam */ 328185377SsamHAL_BOOL 329185377Ssamar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) 330185377Ssam{ 331185377Ssam uint32_t curTrigLevel; 332185377Ssam HAL_INT ints = ar5210GetInterrupts(ah); 333185377Ssam 334185377Ssam /* 335185377Ssam * Disable chip interrupts. This is because halUpdateTxTrigLevel 336185377Ssam * is called from both ISR and non-ISR contexts. 337185377Ssam */ 338185377Ssam (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); 339185377Ssam curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); 340185377Ssam if (bIncTrigLevel){ 341185377Ssam /* increase the trigger level */ 342185377Ssam curTrigLevel = curTrigLevel + 343185377Ssam ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); 344185377Ssam } else { 345185377Ssam /* decrease the trigger level if not already at the minimum */ 346185377Ssam if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { 347185377Ssam /* decrease the trigger level */ 348185377Ssam curTrigLevel--; 349185377Ssam } else { 350185377Ssam /* no update to the trigger level */ 351185377Ssam /* re-enable chip interrupts */ 352185377Ssam ar5210SetInterrupts(ah, ints); 353185377Ssam return AH_FALSE; 354185377Ssam } 355185377Ssam } 356185377Ssam /* Update the trigger level */ 357185377Ssam OS_REG_WRITE(ah, AR_TRIG_LEV, curTrigLevel); 358185377Ssam /* re-enable chip interrupts */ 359185377Ssam ar5210SetInterrupts(ah, ints); 360185377Ssam return AH_TRUE; 361185377Ssam} 362185377Ssam 363185377Ssam/* 364185377Ssam * Set Transmit Enable bits for the specified queues. 365185377Ssam */ 366185377SsamHAL_BOOL 367185377Ssamar5210StartTxDma(struct ath_hal *ah, u_int q) 368185377Ssam{ 369185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 370185377Ssam HAL_TX_QUEUE_INFO *qi; 371185377Ssam 372185377Ssam HALASSERT(q < HAL_NUM_TX_QUEUES); 373185377Ssam 374185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 375185377Ssam qi = &ahp->ah_txq[q]; 376185377Ssam switch (qi->tqi_type) { 377185377Ssam case HAL_TX_QUEUE_DATA: 378185377Ssam OS_REG_WRITE(ah, AR_CR, AR_CR_TXE0); 379185377Ssam break; 380185377Ssam case HAL_TX_QUEUE_CAB: 381185377Ssam OS_REG_WRITE(ah, AR_CR, AR_CR_TXE1); /* enable altq xmit */ 382185377Ssam OS_REG_WRITE(ah, AR_BCR, 383185377Ssam AR_BCR_TQ1V | AR_BCR_BDMAE | AR_BCR_TQ1FV); 384185377Ssam break; 385185377Ssam case HAL_TX_QUEUE_BEACON: 386185377Ssam /* XXX add CR_BCR_BCMD if IBSS mode */ 387185377Ssam OS_REG_WRITE(ah, AR_BCR, AR_BCR_TQ1V | AR_BCR_BDMAE); 388185377Ssam break; 389185377Ssam case HAL_TX_QUEUE_INACTIVE: 390185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 391185377Ssam __func__, q); 392185377Ssam /* fal thru... */ 393185377Ssam default: 394185377Ssam return AH_FALSE; 395185377Ssam } 396185377Ssam return AH_TRUE; 397185377Ssam} 398185377Ssam 399185377Ssamuint32_t 400185377Ssamar5210NumTxPending(struct ath_hal *ah, u_int q) 401185377Ssam{ 402185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 403185377Ssam HAL_TX_QUEUE_INFO *qi; 404185377Ssam uint32_t v; 405185377Ssam 406185377Ssam HALASSERT(q < HAL_NUM_TX_QUEUES); 407185377Ssam 408185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 409185377Ssam qi = &ahp->ah_txq[q]; 410185377Ssam switch (qi->tqi_type) { 411185377Ssam case HAL_TX_QUEUE_DATA: 412185377Ssam v = OS_REG_READ(ah, AR_CFG); 413185377Ssam return MS(v, AR_CFG_TXCNT); 414185377Ssam case HAL_TX_QUEUE_INACTIVE: 415185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 416185377Ssam __func__, q); 417185377Ssam /* fall thru... */ 418185377Ssam default: 419185377Ssam break; 420185377Ssam } 421185377Ssam return 0; 422185377Ssam} 423185377Ssam 424185377Ssam/* 425185377Ssam * Stop transmit on the specified queue 426185377Ssam */ 427185377SsamHAL_BOOL 428185377Ssamar5210StopTxDma(struct ath_hal *ah, u_int q) 429185377Ssam{ 430185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 431185377Ssam HAL_TX_QUEUE_INFO *qi; 432185377Ssam 433185377Ssam HALASSERT(q < HAL_NUM_TX_QUEUES); 434185377Ssam 435185377Ssam HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 436185377Ssam qi = &ahp->ah_txq[q]; 437185377Ssam switch (qi->tqi_type) { 438185377Ssam case HAL_TX_QUEUE_DATA: { 439185377Ssam int i; 440185377Ssam OS_REG_WRITE(ah, AR_CR, AR_CR_TXD0); 441185377Ssam for (i = 0; i < 1000; i++) { 442185377Ssam if ((OS_REG_READ(ah, AR_CFG) & AR_CFG_TXCNT) == 0) 443185377Ssam break; 444185377Ssam OS_DELAY(10); 445185377Ssam } 446185377Ssam OS_REG_WRITE(ah, AR_CR, 0); 447185377Ssam return (i < 1000); 448185377Ssam } 449185377Ssam case HAL_TX_QUEUE_BEACON: 450185377Ssam return ath_hal_wait(ah, AR_BSR, AR_BSR_TXQ1F, 0); 451185377Ssam case HAL_TX_QUEUE_INACTIVE: 452185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 453185377Ssam __func__, q); 454185377Ssam /* fall thru... */ 455185377Ssam default: 456185377Ssam break; 457185377Ssam } 458185377Ssam return AH_FALSE; 459185377Ssam} 460185377Ssam 461185377Ssam/* 462185377Ssam * Descriptor Access Functions 463185377Ssam */ 464185377Ssam 465185377Ssam#define VALID_PKT_TYPES \ 466185377Ssam ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\ 467185377Ssam (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\ 468185377Ssam (1<<HAL_PKT_TYPE_BEACON)) 469185377Ssam#define isValidPktType(_t) ((1<<(_t)) & VALID_PKT_TYPES) 470185377Ssam#define VALID_TX_RATES \ 471185377Ssam ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\ 472185377Ssam (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\ 473185377Ssam (1<<0x1d)|(1<<0x18)|(1<<0x1c)) 474185377Ssam#define isValidTxRate(_r) ((1<<(_r)) & VALID_TX_RATES) 475185377Ssam 476185377SsamHAL_BOOL 477185377Ssamar5210SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, 478185377Ssam u_int pktLen, 479185377Ssam u_int hdrLen, 480185377Ssam HAL_PKT_TYPE type, 481185377Ssam u_int txPower, 482185377Ssam u_int txRate0, u_int txTries0, 483185377Ssam u_int keyIx, 484185377Ssam u_int antMode, 485185377Ssam u_int flags, 486185377Ssam u_int rtsctsRate, 487185377Ssam u_int rtsctsDuration, 488185377Ssam u_int compicvLen, 489185377Ssam u_int compivLen, 490185377Ssam u_int comp) 491185377Ssam{ 492185377Ssam struct ar5210_desc *ads = AR5210DESC(ds); 493185377Ssam uint32_t frtype; 494185377Ssam 495185377Ssam (void) txPower; 496185377Ssam (void) rtsctsDuration; 497185377Ssam 498185377Ssam HALASSERT(txTries0 != 0); 499185377Ssam HALASSERT(isValidPktType(type)); 500185377Ssam HALASSERT(isValidTxRate(txRate0)); 501185377Ssam 502185377Ssam if (type == HAL_PKT_TYPE_BEACON || type == HAL_PKT_TYPE_PROBE_RESP) 503185377Ssam frtype = AR_Frm_NoDelay; 504185377Ssam else 505185377Ssam frtype = type << 26; 506185377Ssam ads->ds_ctl0 = (pktLen & AR_FrameLen) 507185377Ssam | (txRate0 << AR_XmitRate_S) 508185377Ssam | ((hdrLen << AR_HdrLen_S) & AR_HdrLen) 509185377Ssam | frtype 510185377Ssam | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) 511185377Ssam | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) 512185377Ssam | (antMode ? AR_AntModeXmit : 0) 513185377Ssam ; 514185377Ssam if (keyIx != HAL_TXKEYIX_INVALID) { 515185377Ssam ads->ds_ctl1 = (keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx; 516185377Ssam ads->ds_ctl0 |= AR_EncryptKeyValid; 517185377Ssam } else 518185377Ssam ads->ds_ctl1 = 0; 519185377Ssam if (flags & HAL_TXDESC_RTSENA) { 520185377Ssam ads->ds_ctl0 |= AR_RTSCTSEnable; 521243174Sadrian ads->ds_ctl1 |= (rtsctsDuration << AR_RTSDuration_S) 522243174Sadrian & AR_RTSDuration; 523185377Ssam } 524185377Ssam return AH_TRUE; 525185377Ssam} 526185377Ssam 527185377SsamHAL_BOOL 528185377Ssamar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, 529185377Ssam u_int txRate1, u_int txTries1, 530185377Ssam u_int txRate2, u_int txTries2, 531185377Ssam u_int txRate3, u_int txTries3) 532185377Ssam{ 533185377Ssam (void) ah; (void) ds; 534185377Ssam (void) txRate1; (void) txTries1; 535185377Ssam (void) txRate2; (void) txTries2; 536185377Ssam (void) txRate3; (void) txTries3; 537185377Ssam return AH_FALSE; 538185377Ssam} 539185377Ssam 540185377Ssamvoid 541185377Ssamar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) 542185377Ssam{ 543185377Ssam struct ar5210_desc *ads = AR5210DESC(ds); 544185377Ssam 545185377Ssam ads->ds_ctl0 |= AR_TxInterReq; 546185377Ssam} 547185377Ssam 548185377SsamHAL_BOOL 549185377Ssamar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, 550239051Sadrian HAL_DMA_ADDR *bufAddrList, uint32_t *segLenList, u_int descId, 551239051Sadrian u_int qcuId, HAL_BOOL firstSeg, HAL_BOOL lastSeg, 552185377Ssam const struct ath_desc *ds0) 553185377Ssam{ 554185377Ssam struct ar5210_desc *ads = AR5210DESC(ds); 555239051Sadrian uint32_t segLen = segLenList[0]; 556185377Ssam 557185377Ssam HALASSERT((segLen &~ AR_BufLen) == 0); 558185377Ssam 559239051Sadrian ds->ds_data = bufAddrList[0]; 560239051Sadrian 561185377Ssam if (firstSeg) { 562185377Ssam /* 563185377Ssam * First descriptor, don't clobber xmit control data 564185377Ssam * setup by ar5210SetupTxDesc. 565185377Ssam */ 566185377Ssam ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); 567185377Ssam } else if (lastSeg) { /* !firstSeg && lastSeg */ 568185377Ssam /* 569185377Ssam * Last descriptor in a multi-descriptor frame, 570185377Ssam * copy the transmit parameters from the first 571185377Ssam * frame for processing on completion. 572185377Ssam */ 573185377Ssam ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; 574185377Ssam ads->ds_ctl1 = segLen; 575185377Ssam } else { /* !firstSeg && !lastSeg */ 576185377Ssam /* 577185377Ssam * Intermediate descriptor in a multi-descriptor frame. 578185377Ssam */ 579185377Ssam ads->ds_ctl0 = 0; 580185377Ssam ads->ds_ctl1 = segLen | AR_More; 581185377Ssam } 582185377Ssam ads->ds_status0 = ads->ds_status1 = 0; 583185377Ssam return AH_TRUE; 584185377Ssam} 585185377Ssam 586185377Ssam/* 587185377Ssam * Processing of HW TX descriptor. 588185377Ssam */ 589185377SsamHAL_STATUS 590185377Ssamar5210ProcTxDesc(struct ath_hal *ah, 591185377Ssam struct ath_desc *ds, struct ath_tx_status *ts) 592185377Ssam{ 593185377Ssam struct ar5210_desc *ads = AR5210DESC(ds); 594185377Ssam 595185377Ssam if ((ads->ds_status1 & AR_Done) == 0) 596185377Ssam return HAL_EINPROGRESS; 597185377Ssam 598185377Ssam /* Update software copies of the HW status */ 599185377Ssam ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; 600185377Ssam ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); 601185377Ssam ts->ts_status = 0; 602185377Ssam if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { 603185377Ssam if (ads->ds_status0 & AR_ExcessiveRetries) 604185377Ssam ts->ts_status |= HAL_TXERR_XRETRY; 605185377Ssam if (ads->ds_status0 & AR_Filtered) 606185377Ssam ts->ts_status |= HAL_TXERR_FILT; 607185377Ssam if (ads->ds_status0 & AR_FIFOUnderrun) 608185377Ssam ts->ts_status |= HAL_TXERR_FIFO; 609185377Ssam } 610185377Ssam ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); 611185377Ssam ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); 612185377Ssam ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); 613185377Ssam ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); 614185377Ssam ts->ts_antenna = 0; /* NB: don't know */ 615185377Ssam ts->ts_finaltsi = 0; 616185377Ssam 617185377Ssam return HAL_OK; 618185377Ssam} 619185377Ssam 620185377Ssam/* 621185377Ssam * Determine which tx queues need interrupt servicing. 622185377Ssam * STUB. 623185377Ssam */ 624185377Ssamvoid 625185377Ssamar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) 626185377Ssam{ 627185377Ssam return; 628185377Ssam} 629217621Sadrian 630217621Sadrian/* 631217621Sadrian * Retrieve the rate table from the given TX completion descriptor 632217621Sadrian */ 633217621SadrianHAL_BOOL 634217621Sadrianar5210GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int *rates, int *tries) 635217621Sadrian{ 636217621Sadrian return AH_FALSE; 637217621Sadrian} 638238607Sadrian 639238607Sadrian/* 640238607Sadrian * Set the TX descriptor link pointer 641238607Sadrian */ 642238607Sadrianvoid 643238607Sadrianar5210SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) 644238607Sadrian{ 645238607Sadrian struct ar5210_desc *ads = AR5210DESC(ds); 646238607Sadrian 647238607Sadrian ads->ds_link = link; 648238607Sadrian} 649238607Sadrian 650238607Sadrian/* 651238607Sadrian * Get the TX descriptor link pointer 652238607Sadrian */ 653238607Sadrianvoid 654238607Sadrianar5210GetTxDescLink(struct ath_hal *ah, void *ds, uint32_t *link) 655238607Sadrian{ 656238607Sadrian struct ar5210_desc *ads = AR5210DESC(ds); 657238607Sadrian 658238607Sadrian *link = ads->ds_link; 659238607Sadrian} 660238607Sadrian 661238607Sadrian/* 662238607Sadrian * Get a pointer to the TX descriptor link pointer 663238607Sadrian */ 664238607Sadrianvoid 665238607Sadrianar5210GetTxDescLinkPtr(struct ath_hal *ah, void *ds, uint32_t **linkptr) 666238607Sadrian{ 667238607Sadrian struct ar5210_desc *ads = AR5210DESC(ds); 668238607Sadrian 669238607Sadrian *linkptr = &ads->ds_link; 670238607Sadrian} 671