ar5210_xmit.c revision 186333
12522Sraf/* 22522Sraf * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 32522Sraf * Copyright (c) 2002-2004 Atheros Communications, Inc. 42522Sraf * 52522Sraf * Permission to use, copy, modify, and/or distribute this software for any 62522Sraf * purpose with or without fee is hereby granted, provided that the above 72522Sraf * copyright notice and this permission notice appear in all copies. 82522Sraf * 92522Sraf * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 102522Sraf * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 112522Sraf * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 122522Sraf * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 132522Sraf * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 142522Sraf * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 152522Sraf * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 162522Sraf * 172522Sraf * $Id: ar5210_xmit.c,v 1.5 2008/11/10 04:08:02 sam Exp $ 182522Sraf */ 192522Sraf#include "opt_ah.h" 202522Sraf 212522Sraf#include "ah.h" 2212326Sgww@eng.sun.com#include "ah_internal.h" 232522Sraf#include "ah_desc.h" 242522Sraf 258744SAli.Bahrami@Sun.COM#include "ar5210/ar5210.h" 268744SAli.Bahrami@Sun.COM#include "ar5210/ar5210reg.h" 278744SAli.Bahrami@Sun.COM#include "ar5210/ar5210phy.h" 288744SAli.Bahrami@Sun.COM#include "ar5210/ar5210desc.h" 298744SAli.Bahrami@Sun.COM 308744SAli.Bahrami@Sun.COM/* 318744SAli.Bahrami@Sun.COM * Set the properties of the tx queue with the parameters 328744SAli.Bahrami@Sun.COM * from qInfo. The queue must previously have been setup 338744SAli.Bahrami@Sun.COM * with a call to ar5210SetupTxQueue. 348744SAli.Bahrami@Sun.COM */ 358744SAli.Bahrami@Sun.COMHAL_BOOL 368744SAli.Bahrami@Sun.COMar5210SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo) 378744SAli.Bahrami@Sun.COM{ 388744SAli.Bahrami@Sun.COM struct ath_hal_5210 *ahp = AH5210(ah); 3912692SAli.Bahrami@Oracle.COM 4012692SAli.Bahrami@Oracle.COM if (q >= HAL_NUM_TX_QUEUES) { 4112692SAli.Bahrami@Oracle.COM HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 422522Sraf __func__, q); 432522Sraf return AH_FALSE; 442522Sraf } 452522Sraf return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo); 462522Sraf} 472522Sraf 482522Sraf/* 492522Sraf * Return the properties for the specified tx queue. 502522Sraf */ 512522SrafHAL_BOOL 522522Srafar5210GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) 532522Sraf{ 542522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 552522Sraf 562522Sraf if (q >= HAL_NUM_TX_QUEUES) { 5712692SAli.Bahrami@Oracle.COM HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 582522Sraf __func__, q); 592522Sraf return AH_FALSE; 602522Sraf } 612522Sraf return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]); 6212692SAli.Bahrami@Oracle.COM} 632522Sraf 642522Sraf/* 652522Sraf * Allocate and initialize a tx DCU/QCU combination. 662522Sraf */ 672522Srafint 682522Srafar5210SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type, 692522Sraf const HAL_TXQ_INFO *qInfo) 702522Sraf{ 712522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 7212692SAli.Bahrami@Oracle.COM HAL_TX_QUEUE_INFO *qi; 732522Sraf int q; 742522Sraf 752522Sraf switch (type) { 762522Sraf case HAL_TX_QUEUE_BEACON: 772522Sraf q = 2; 782522Sraf break; 792522Sraf case HAL_TX_QUEUE_CAB: 802522Sraf q = 1; 812522Sraf break; 822522Sraf case HAL_TX_QUEUE_DATA: 832522Sraf q = 0; 842522Sraf break; 852522Sraf default: 862522Sraf HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n", 872522Sraf __func__, type); 882522Sraf return -1; 892522Sraf } 902522Sraf 912522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q); 922522Sraf 932522Sraf qi = &ahp->ah_txq[q]; 942522Sraf if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { 952522Sraf HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n", 962522Sraf __func__, q); 972522Sraf return -1; 982522Sraf } 992522Sraf OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); 1002522Sraf qi->tqi_type = type; 1012522Sraf if (qInfo == AH_NULL) { 1022522Sraf /* by default enable OK+ERR+DESC+URN interrupts */ 1032522Sraf qi->tqi_qflags = 1042522Sraf HAL_TXQ_TXOKINT_ENABLE 1052522Sraf | HAL_TXQ_TXERRINT_ENABLE 1062522Sraf | HAL_TXQ_TXDESCINT_ENABLE 1072522Sraf | HAL_TXQ_TXURNINT_ENABLE 1082522Sraf ; 1092522Sraf qi->tqi_aifs = INIT_AIFS; 1102522Sraf qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ 1112522Sraf qi->tqi_shretry = INIT_SH_RETRY; 1122522Sraf qi->tqi_lgretry = INIT_LG_RETRY; 1132522Sraf } else 1142522Sraf (void) ar5210SetTxQueueProps(ah, q, qInfo); 1152522Sraf /* NB: must be followed by ar5210ResetTxQueue */ 11612692SAli.Bahrami@Oracle.COM return q; 1172522Sraf} 1182522Sraf 1192522Sraf/* 1202522Sraf * Free a tx DCU/QCU combination. 1212522Sraf */ 1222522SrafHAL_BOOL 1232522Srafar5210ReleaseTxQueue(struct ath_hal *ah, u_int q) 1242522Sraf{ 1252522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 1262522Sraf HAL_TX_QUEUE_INFO *qi; 1272522Sraf 1282522Sraf if (q >= HAL_NUM_TX_QUEUES) { 1292522Sraf HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 1302522Sraf __func__, q); 1315012Sgww return AH_FALSE; 1322522Sraf } 1332522Sraf qi = &ahp->ah_txq[q]; 1342522Sraf if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 1352522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 1362522Sraf __func__, q); 1372522Sraf return AH_FALSE; 1382522Sraf } 1392522Sraf 1402522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q); 1412522Sraf 1425344Stz204579 qi->tqi_type = HAL_TX_QUEUE_INACTIVE; 1432522Sraf ahp->ah_txOkInterruptMask &= ~(1 << q); 1447753STon.Nguyen@Sun.COM ahp->ah_txErrInterruptMask &= ~(1 << q); 1452522Sraf ahp->ah_txDescInterruptMask &= ~(1 << q); 1462522Sraf ahp->ah_txEolInterruptMask &= ~(1 << q); 1472522Sraf ahp->ah_txUrnInterruptMask &= ~(1 << q); 1486680Sgww 1492522Sraf return AH_TRUE; 1502522Sraf#undef N 1512522Sraf} 1522522Sraf 1532522SrafHAL_BOOL 1542522Srafar5210ResetTxQueue(struct ath_hal *ah, u_int q) 1552522Sraf{ 1562522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 1572522Sraf HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; 1585777Stw21770 HAL_TX_QUEUE_INFO *qi; 1592522Sraf uint32_t cwMin; 1607496Sgww@eng.sun.com 1612522Sraf if (q >= HAL_NUM_TX_QUEUES) { 1622522Sraf HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", 1632522Sraf __func__, q); 1642522Sraf return AH_FALSE; 1652522Sraf } 1662522Sraf qi = &ahp->ah_txq[q]; 1672522Sraf if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 1682522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 1692522Sraf __func__, q); 1702522Sraf return AH_FALSE; 1712522Sraf } 1722522Sraf 1732522Sraf /* 1742522Sraf * Ignore any non-data queue(s). 1752522Sraf */ 1762522Sraf if (qi->tqi_type != HAL_TX_QUEUE_DATA) 1772522Sraf return AH_TRUE; 1782522Sraf 1792522Sraf /* Set turbo mode / base mode parameters on or off */ 1802522Sraf if (IS_CHAN_TURBO(chan)) { 1812522Sraf OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME_TURBO); 1822522Sraf OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT_TURBO); 1832522Sraf OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY_TURBO); 1842522Sraf OS_REG_WRITE(ah, AR_IFS0, 1852522Sraf ((INIT_SIFS_TURBO + qi->tqi_aifs * INIT_SLOT_TIME_TURBO) 1862522Sraf << AR_IFS0_DIFS_S) 1872522Sraf | INIT_SIFS_TURBO); 1882522Sraf OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL_TURBO); 1892522Sraf OS_REG_WRITE(ah, AR_PHY(17), 1902522Sraf (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x38); 1912522Sraf OS_REG_WRITE(ah, AR_PHY_FRCTL, 1922522Sraf AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 1932522Sraf AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 1942522Sraf AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 1952522Sraf 0x2020 | 1962522Sraf AR_PHY_TURBO_MODE | AR_PHY_TURBO_SHORT); 1972522Sraf } else { 1982522Sraf OS_REG_WRITE(ah, AR_SLOT_TIME, INIT_SLOT_TIME); 1992522Sraf OS_REG_WRITE(ah, AR_TIME_OUT, INIT_ACK_CTS_TIMEOUT); 2002522Sraf OS_REG_WRITE(ah, AR_USEC, INIT_TRANSMIT_LATENCY); 2012522Sraf OS_REG_WRITE(ah, AR_IFS0, 2022522Sraf ((INIT_SIFS + qi->tqi_aifs * INIT_SLOT_TIME) 2032522Sraf << AR_IFS0_DIFS_S) 2042522Sraf | INIT_SIFS); 2052522Sraf OS_REG_WRITE(ah, AR_IFS1, INIT_PROTO_TIME_CNTRL); 2062522Sraf OS_REG_WRITE(ah, AR_PHY(17), 2072522Sraf (OS_REG_READ(ah, AR_PHY(17)) & ~0x7F) | 0x1C); 2082522Sraf OS_REG_WRITE(ah, AR_PHY_FRCTL, 2092522Sraf AR_PHY_SERVICE_ERR | AR_PHY_TXURN_ERR | 2102522Sraf AR_PHY_ILLLEN_ERR | AR_PHY_ILLRATE_ERR | 2112522Sraf AR_PHY_PARITY_ERR | AR_PHY_TIMING_ERR | 0x1020); 2122522Sraf } 2132522Sraf 2142522Sraf if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) 2152522Sraf cwMin = INIT_CWMIN; 2162522Sraf else 2172522Sraf cwMin = qi->tqi_cwmin; 2182522Sraf 2192522Sraf /* Set cwmin and retry limit values */ 2202522Sraf OS_REG_WRITE(ah, AR_RETRY_LMT, 2212522Sraf (cwMin << AR_RETRY_LMT_CW_MIN_S) 2222522Sraf | SM(INIT_SLG_RETRY, AR_RETRY_LMT_SLG_RETRY) 2232522Sraf | SM(INIT_SSH_RETRY, AR_RETRY_LMT_SSH_RETRY) 2242522Sraf | SM(qi->tqi_lgretry, AR_RETRY_LMT_LG_RETRY) 2252522Sraf | SM(qi->tqi_shretry, AR_RETRY_LMT_SH_RETRY) 2262522Sraf ); 2272522Sraf 2282522Sraf if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) 2292522Sraf ahp->ah_txOkInterruptMask |= 1 << q; 2302522Sraf else 2312522Sraf ahp->ah_txOkInterruptMask &= ~(1 << q); 2322522Sraf if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) 2332522Sraf ahp->ah_txErrInterruptMask |= 1 << q; 2342522Sraf else 2352522Sraf ahp->ah_txErrInterruptMask &= ~(1 << q); 2362522Sraf if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE) 2372522Sraf ahp->ah_txDescInterruptMask |= 1 << q; 2382522Sraf else 2392522Sraf ahp->ah_txDescInterruptMask &= ~(1 << q); 2402522Sraf if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) 2412522Sraf ahp->ah_txEolInterruptMask |= 1 << q; 2422522Sraf else 2432522Sraf ahp->ah_txEolInterruptMask &= ~(1 << q); 2442522Sraf if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) 2452522Sraf ahp->ah_txUrnInterruptMask |= 1 << q; 2462522Sraf else 2472522Sraf ahp->ah_txUrnInterruptMask &= ~(1 << q); 2482522Sraf 2492522Sraf return AH_TRUE; 2502522Sraf} 2512522Sraf 2522522Sraf/* 2532522Sraf * Get the TXDP for the "main" data queue. Needs to be extended 2542522Sraf * for multiple Q functionality 2552522Sraf */ 2562522Srafuint32_t 2572522Srafar5210GetTxDP(struct ath_hal *ah, u_int q) 2582522Sraf{ 2592522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 2605537Sgww HAL_TX_QUEUE_INFO *qi; 2612522Sraf 2622522Sraf HALASSERT(q < HAL_NUM_TX_QUEUES); 2632522Sraf 2642522Sraf qi = &ahp->ah_txq[q]; 2652522Sraf switch (qi->tqi_type) { 2662522Sraf case HAL_TX_QUEUE_DATA: 2675012Sgww return OS_REG_READ(ah, AR_TXDP0); 26811893Sgww@eng.sun.com case HAL_TX_QUEUE_INACTIVE: 2692522Sraf HALDEBUG(ah, HAL_DEBUG_ANY, "%s: inactive queue %u\n", 2705012Sgww __func__, q); 2715012Sgww /* fall thru... */ 2725012Sgww default: 2735012Sgww break; 2745012Sgww } 2755012Sgww return 0xffffffff; 2765012Sgww} 2772522Sraf 2785012Sgww/* 2792522Sraf * Set the TxDP for the "main" data queue. 2802522Sraf */ 2812522SrafHAL_BOOL 2822522Srafar5210SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp) 28312326Sgww@eng.sun.com{ 2842522Sraf struct ath_hal_5210 *ahp = AH5210(ah); 2852522Sraf HAL_TX_QUEUE_INFO *qi; 2862522Sraf 2872522Sraf HALASSERT(q < HAL_NUM_TX_QUEUES); 2882522Sraf 2892522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u 0x%x\n", 29011529SJan.Parcel@Sun.COM __func__, q, txdp); 2912522Sraf qi = &ahp->ah_txq[q]; 2922522Sraf switch (qi->tqi_type) { 29312918SJan.Friedel@Sun.COM case HAL_TX_QUEUE_DATA: 29412918SJan.Friedel@Sun.COM#ifdef AH_DEBUG 29512918SJan.Friedel@Sun.COM /* 29612918SJan.Friedel@Sun.COM * Make sure that TXE is deasserted before setting the 29712918SJan.Friedel@Sun.COM * TXDP. If TXE is still asserted, setting TXDP will 29812918SJan.Friedel@Sun.COM * have no effect. 29912918SJan.Friedel@Sun.COM */ 30012918SJan.Friedel@Sun.COM if (OS_REG_READ(ah, AR_CR) & AR_CR_TXE0) 30112918SJan.Friedel@Sun.COM ath_hal_printf(ah, "%s: TXE asserted; AR_CR=0x%x\n", 30212918SJan.Friedel@Sun.COM __func__, OS_REG_READ(ah, AR_CR)); 30312918SJan.Friedel@Sun.COM#endif 30412918SJan.Friedel@Sun.COM OS_REG_WRITE(ah, AR_TXDP0, txdp); 30512918SJan.Friedel@Sun.COM break; 30612918SJan.Friedel@Sun.COM case HAL_TX_QUEUE_BEACON: 30712918SJan.Friedel@Sun.COM case HAL_TX_QUEUE_CAB: 30812918SJan.Friedel@Sun.COM OS_REG_WRITE(ah, AR_TXDP1, txdp); 30912918SJan.Friedel@Sun.COM break; 31012918SJan.Friedel@Sun.COM case HAL_TX_QUEUE_INACTIVE: 3112522Sraf HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n", 3122522Sraf __func__, q); 3132522Sraf /* fall thru... */ 3142522Sraf default: 3152522Sraf return AH_FALSE; 3162522Sraf } 31712918SJan.Friedel@Sun.COM return AH_TRUE; 3182522Sraf} 3192522Sraf 3202522Sraf/* 3212522Sraf * Update Tx FIFO trigger level. 3222522Sraf * 3232522Sraf * Set bIncTrigLevel to TRUE to increase the trigger level. 3242522Sraf * Set bIncTrigLevel to FALSE to decrease the trigger level. 3252522Sraf * 3262522Sraf * Returns TRUE if the trigger level was updated 3272522Sraf */ 3282522SrafHAL_BOOL 3292522Srafar5210UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel) 3302522Sraf{ 33112918SJan.Friedel@Sun.COM uint32_t curTrigLevel; 3322522Sraf HAL_INT ints = ar5210GetInterrupts(ah); 33312918SJan.Friedel@Sun.COM 33412918SJan.Friedel@Sun.COM /* 33512918SJan.Friedel@Sun.COM * Disable chip interrupts. This is because halUpdateTxTrigLevel 3362522Sraf * is called from both ISR and non-ISR contexts. 3372522Sraf */ 3382522Sraf (void) ar5210SetInterrupts(ah, ints &~ HAL_INT_GLOBAL); 3392522Sraf curTrigLevel = OS_REG_READ(ah, AR_TRIG_LEV); 3402522Sraf if (bIncTrigLevel){ 3412522Sraf /* increase the trigger level */ 3424292Sab196087 curTrigLevel = curTrigLevel + 3434292Sab196087 ((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2); 34412692SAli.Bahrami@Oracle.COM } else { 34512692SAli.Bahrami@Oracle.COM /* decrease the trigger level if not already at the minimum */ 34612692SAli.Bahrami@Oracle.COM if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) { 34712692SAli.Bahrami@Oracle.COM /* decrease the trigger level */ 34812692SAli.Bahrami@Oracle.COM curTrigLevel--; 3494292Sab196087 } else { 3504292Sab196087 /* no update to the trigger level */ 3512522Sraf /* re-enable chip interrupts */ 3522522Sraf 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 */ 366HAL_BOOL 367ar5210StartTxDma(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 399uint32_t 400ar5210NumTxPending(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 */ 427HAL_BOOL 428ar5210StopTxDma(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 476HAL_BOOL 477ar5210SetupTxDesc(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; 522 } 523 return AH_TRUE; 524} 525 526HAL_BOOL 527ar5210SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, 528 u_int txRate1, u_int txTries1, 529 u_int txRate2, u_int txTries2, 530 u_int txRate3, u_int txTries3) 531{ 532 (void) ah; (void) ds; 533 (void) txRate1; (void) txTries1; 534 (void) txRate2; (void) txTries2; 535 (void) txRate3; (void) txTries3; 536 return AH_FALSE; 537} 538 539void 540ar5210IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds) 541{ 542 struct ar5210_desc *ads = AR5210DESC(ds); 543 544 ads->ds_ctl0 |= AR_TxInterReq; 545} 546 547HAL_BOOL 548ar5210FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, 549 u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, 550 const struct ath_desc *ds0) 551{ 552 struct ar5210_desc *ads = AR5210DESC(ds); 553 554 HALASSERT((segLen &~ AR_BufLen) == 0); 555 556 if (firstSeg) { 557 /* 558 * First descriptor, don't clobber xmit control data 559 * setup by ar5210SetupTxDesc. 560 */ 561 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); 562 } else if (lastSeg) { /* !firstSeg && lastSeg */ 563 /* 564 * Last descriptor in a multi-descriptor frame, 565 * copy the transmit parameters from the first 566 * frame for processing on completion. 567 */ 568 ads->ds_ctl0 = AR5210DESC_CONST(ds0)->ds_ctl0; 569 ads->ds_ctl1 = segLen; 570 } else { /* !firstSeg && !lastSeg */ 571 /* 572 * Intermediate descriptor in a multi-descriptor frame. 573 */ 574 ads->ds_ctl0 = 0; 575 ads->ds_ctl1 = segLen | AR_More; 576 } 577 ads->ds_status0 = ads->ds_status1 = 0; 578 return AH_TRUE; 579} 580 581/* 582 * Processing of HW TX descriptor. 583 */ 584HAL_STATUS 585ar5210ProcTxDesc(struct ath_hal *ah, 586 struct ath_desc *ds, struct ath_tx_status *ts) 587{ 588 struct ar5210_desc *ads = AR5210DESC(ds); 589 590 if ((ads->ds_status1 & AR_Done) == 0) 591 return HAL_EINPROGRESS; 592 593 /* Update software copies of the HW status */ 594 ts->ts_seqnum = ads->ds_status1 & AR_SeqNum; 595 ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp); 596 ts->ts_status = 0; 597 if ((ads->ds_status0 & AR_FrmXmitOK) == 0) { 598 if (ads->ds_status0 & AR_ExcessiveRetries) 599 ts->ts_status |= HAL_TXERR_XRETRY; 600 if (ads->ds_status0 & AR_Filtered) 601 ts->ts_status |= HAL_TXERR_FILT; 602 if (ads->ds_status0 & AR_FIFOUnderrun) 603 ts->ts_status |= HAL_TXERR_FIFO; 604 } 605 ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate); 606 ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength); 607 ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt); 608 ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt); 609 ts->ts_antenna = 0; /* NB: don't know */ 610 ts->ts_finaltsi = 0; 611 612 return HAL_OK; 613} 614 615/* 616 * Determine which tx queues need interrupt servicing. 617 * STUB. 618 */ 619void 620ar5210GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs) 621{ 622 return; 623} 624