Home | History | Annotate | Line # | Download | only in ar5211
      1  1.1  alc /*
      2  1.1  alc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  1.1  alc  * Copyright (c) 2002-2006 Atheros Communications, Inc.
      4  1.1  alc  *
      5  1.1  alc  * Permission to use, copy, modify, and/or distribute this software for any
      6  1.1  alc  * purpose with or without fee is hereby granted, provided that the above
      7  1.1  alc  * copyright notice and this permission notice appear in all copies.
      8  1.1  alc  *
      9  1.1  alc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  1.1  alc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  1.1  alc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  1.1  alc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  1.1  alc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  1.1  alc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  1.1  alc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  1.1  alc  *
     17  1.1  alc  * $Id: ar5211_xmit.c,v 1.1.1.1 2008/12/11 04:46:34 alc Exp $
     18  1.1  alc  */
     19  1.1  alc #include "opt_ah.h"
     20  1.1  alc 
     21  1.1  alc #include "ah.h"
     22  1.1  alc #include "ah_internal.h"
     23  1.1  alc #include "ah_desc.h"
     24  1.1  alc 
     25  1.1  alc #include "ar5211/ar5211.h"
     26  1.1  alc #include "ar5211/ar5211reg.h"
     27  1.1  alc #include "ar5211/ar5211desc.h"
     28  1.1  alc 
     29  1.1  alc /*
     30  1.1  alc  * Update Tx FIFO trigger level.
     31  1.1  alc  *
     32  1.1  alc  * Set bIncTrigLevel to TRUE to increase the trigger level.
     33  1.1  alc  * Set bIncTrigLevel to FALSE to decrease the trigger level.
     34  1.1  alc  *
     35  1.1  alc  * Returns TRUE if the trigger level was updated
     36  1.1  alc  */
     37  1.1  alc HAL_BOOL
     38  1.1  alc ar5211UpdateTxTrigLevel(struct ath_hal *ah, HAL_BOOL bIncTrigLevel)
     39  1.1  alc {
     40  1.1  alc 	uint32_t curTrigLevel, txcfg;
     41  1.1  alc 	HAL_INT ints = ar5211GetInterrupts(ah);
     42  1.1  alc 
     43  1.1  alc 	/*
     44  1.1  alc 	 * Disable chip interrupts. This is because halUpdateTxTrigLevel
     45  1.1  alc 	 * is called from both ISR and non-ISR contexts.
     46  1.1  alc 	 */
     47  1.1  alc 	ar5211SetInterrupts(ah, ints &~ HAL_INT_GLOBAL);
     48  1.1  alc 	txcfg = OS_REG_READ(ah, AR_TXCFG);
     49  1.1  alc 	curTrigLevel = (txcfg & AR_TXCFG_FTRIG_M) >> AR_TXCFG_FTRIG_S;
     50  1.1  alc 	if (bIncTrigLevel){
     51  1.1  alc 		/* increase the trigger level */
     52  1.1  alc 		curTrigLevel = curTrigLevel +
     53  1.1  alc 			((MAX_TX_FIFO_THRESHOLD - curTrigLevel) / 2);
     54  1.1  alc 	} else {
     55  1.1  alc 		/* decrease the trigger level if not already at the minimum */
     56  1.1  alc 		if (curTrigLevel > MIN_TX_FIFO_THRESHOLD) {
     57  1.1  alc 			/* decrease the trigger level */
     58  1.1  alc 			curTrigLevel--;
     59  1.1  alc 		} else {
     60  1.1  alc 			/* no update to the trigger level */
     61  1.1  alc 			/* re-enable chip interrupts */
     62  1.1  alc 			ar5211SetInterrupts(ah, ints);
     63  1.1  alc 			return AH_FALSE;
     64  1.1  alc 		}
     65  1.1  alc 	}
     66  1.1  alc 	/* Update the trigger level */
     67  1.1  alc 	OS_REG_WRITE(ah, AR_TXCFG, (txcfg &~ AR_TXCFG_FTRIG_M) |
     68  1.1  alc 		((curTrigLevel << AR_TXCFG_FTRIG_S) & AR_TXCFG_FTRIG_M));
     69  1.1  alc 	/* re-enable chip interrupts */
     70  1.1  alc 	ar5211SetInterrupts(ah, ints);
     71  1.1  alc 	return AH_TRUE;
     72  1.1  alc }
     73  1.1  alc 
     74  1.1  alc /*
     75  1.1  alc  * Set the properties of the tx queue with the parameters
     76  1.1  alc  * from qInfo.  The queue must previously have been setup
     77  1.1  alc  * with a call to ar5211SetupTxQueue.
     78  1.1  alc  */
     79  1.1  alc HAL_BOOL
     80  1.1  alc ar5211SetTxQueueProps(struct ath_hal *ah, int q, const HAL_TXQ_INFO *qInfo)
     81  1.1  alc {
     82  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
     83  1.1  alc 
     84  1.1  alc 	if (q >= HAL_NUM_TX_QUEUES) {
     85  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
     86  1.1  alc 		    __func__, q);
     87  1.1  alc 		return AH_FALSE;
     88  1.1  alc 	}
     89  1.1  alc 	return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], qInfo);
     90  1.1  alc }
     91  1.1  alc 
     92  1.1  alc /*
     93  1.1  alc  * Return the properties for the specified tx queue.
     94  1.1  alc  */
     95  1.1  alc HAL_BOOL
     96  1.1  alc ar5211GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo)
     97  1.1  alc {
     98  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
     99  1.1  alc 
    100  1.1  alc 	if (q >= HAL_NUM_TX_QUEUES) {
    101  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
    102  1.1  alc 		    __func__, q);
    103  1.1  alc 		return AH_FALSE;
    104  1.1  alc 	}
    105  1.1  alc 	return ath_hal_getTxQProps(ah, qInfo, &ahp->ah_txq[q]);
    106  1.1  alc }
    107  1.1  alc 
    108  1.1  alc /*
    109  1.1  alc  * Allocate and initialize a tx DCU/QCU combination.
    110  1.1  alc  */
    111  1.1  alc int
    112  1.1  alc ar5211SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
    113  1.1  alc 	const HAL_TXQ_INFO *qInfo)
    114  1.1  alc {
    115  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
    116  1.1  alc 	HAL_TX_QUEUE_INFO *qi;
    117  1.1  alc 	int q;
    118  1.1  alc 
    119  1.1  alc 	switch (type) {
    120  1.1  alc 	case HAL_TX_QUEUE_BEACON:
    121  1.1  alc 		q = 9;
    122  1.1  alc 		break;
    123  1.1  alc 	case HAL_TX_QUEUE_CAB:
    124  1.1  alc 		q = 8;
    125  1.1  alc 		break;
    126  1.1  alc 	case HAL_TX_QUEUE_DATA:
    127  1.1  alc 		q = 0;
    128  1.1  alc 		if (ahp->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE)
    129  1.1  alc 			return q;
    130  1.1  alc 		break;
    131  1.1  alc 	default:
    132  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad tx queue type %u\n",
    133  1.1  alc 		    __func__, type);
    134  1.1  alc 		return -1;
    135  1.1  alc 	}
    136  1.1  alc 
    137  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
    138  1.1  alc 
    139  1.1  alc 	qi = &ahp->ah_txq[q];
    140  1.1  alc 	if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) {
    141  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: tx queue %u already active\n",
    142  1.1  alc 		    __func__, q);
    143  1.1  alc 		return -1;
    144  1.1  alc 	}
    145  1.1  alc 	OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO));
    146  1.1  alc 	qi->tqi_type = type;
    147  1.1  alc 	if (qInfo == AH_NULL) {
    148  1.1  alc 		/* by default enable OK+ERR+DESC+URN interrupts */
    149  1.1  alc 		qi->tqi_qflags =
    150  1.1  alc 			  HAL_TXQ_TXOKINT_ENABLE
    151  1.1  alc 			| HAL_TXQ_TXERRINT_ENABLE
    152  1.1  alc 			| HAL_TXQ_TXDESCINT_ENABLE
    153  1.1  alc 			| HAL_TXQ_TXURNINT_ENABLE
    154  1.1  alc 			;
    155  1.1  alc 		qi->tqi_aifs = INIT_AIFS;
    156  1.1  alc 		qi->tqi_cwmin = HAL_TXQ_USEDEFAULT;	/* NB: do at reset */
    157  1.1  alc 		qi->tqi_cwmax = INIT_CWMAX;
    158  1.1  alc 		qi->tqi_shretry = INIT_SH_RETRY;
    159  1.1  alc 		qi->tqi_lgretry = INIT_LG_RETRY;
    160  1.1  alc 	} else
    161  1.1  alc 		(void) ar5211SetTxQueueProps(ah, q, qInfo);
    162  1.1  alc 	return q;
    163  1.1  alc }
    164  1.1  alc 
    165  1.1  alc /*
    166  1.1  alc  * Update the h/w interrupt registers to reflect a tx q's configuration.
    167  1.1  alc  */
    168  1.1  alc static void
    169  1.1  alc setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi)
    170  1.1  alc {
    171  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
    172  1.1  alc 
    173  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
    174  1.1  alc 	    "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", __func__
    175  1.1  alc 		, ahp->ah_txOkInterruptMask
    176  1.1  alc 		, ahp->ah_txErrInterruptMask
    177  1.1  alc 		, ahp->ah_txDescInterruptMask
    178  1.1  alc 		, ahp->ah_txEolInterruptMask
    179  1.1  alc 		, ahp->ah_txUrnInterruptMask
    180  1.1  alc 	);
    181  1.1  alc 
    182  1.1  alc 	OS_REG_WRITE(ah, AR_IMR_S0,
    183  1.1  alc 		  SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
    184  1.1  alc 		| SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)
    185  1.1  alc 	);
    186  1.1  alc 	OS_REG_WRITE(ah, AR_IMR_S1,
    187  1.1  alc 		  SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
    188  1.1  alc 		| SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)
    189  1.1  alc 	);
    190  1.1  alc 	OS_REG_RMW_FIELD(ah, AR_IMR_S2,
    191  1.1  alc 		AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
    192  1.1  alc }
    193  1.1  alc 
    194  1.1  alc 
    195  1.1  alc /*
    196  1.1  alc  * Free a tx DCU/QCU combination.
    197  1.1  alc  */
    198  1.1  alc HAL_BOOL
    199  1.1  alc ar5211ReleaseTxQueue(struct ath_hal *ah, u_int q)
    200  1.1  alc {
    201  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
    202  1.1  alc 	HAL_TX_QUEUE_INFO *qi;
    203  1.1  alc 
    204  1.1  alc 	if (q >= HAL_NUM_TX_QUEUES) {
    205  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
    206  1.1  alc 		    __func__, q);
    207  1.1  alc 		return AH_FALSE;
    208  1.1  alc 	}
    209  1.1  alc 	qi = &ahp->ah_txq[q];
    210  1.1  alc 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
    211  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
    212  1.1  alc 		    __func__, q);
    213  1.1  alc 		return AH_FALSE;
    214  1.1  alc 	}
    215  1.1  alc 
    216  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: release queue %u\n", __func__, q);
    217  1.1  alc 
    218  1.1  alc 	qi->tqi_type = HAL_TX_QUEUE_INACTIVE;
    219  1.1  alc 	ahp->ah_txOkInterruptMask &= ~(1 << q);
    220  1.1  alc 	ahp->ah_txErrInterruptMask &= ~(1 << q);
    221  1.1  alc 	ahp->ah_txDescInterruptMask &= ~(1 << q);
    222  1.1  alc 	ahp->ah_txEolInterruptMask &= ~(1 << q);
    223  1.1  alc 	ahp->ah_txUrnInterruptMask &= ~(1 << q);
    224  1.1  alc 	setTxQInterrupts(ah, qi);
    225  1.1  alc 
    226  1.1  alc 	return AH_TRUE;
    227  1.1  alc }
    228  1.1  alc 
    229  1.1  alc /*
    230  1.1  alc  * Set the retry, aifs, cwmin/max, readyTime regs for specified queue
    231  1.1  alc  */
    232  1.1  alc HAL_BOOL
    233  1.1  alc ar5211ResetTxQueue(struct ath_hal *ah, u_int q)
    234  1.1  alc {
    235  1.1  alc 	struct ath_hal_5211 *ahp = AH5211(ah);
    236  1.1  alc 	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
    237  1.1  alc 	HAL_TX_QUEUE_INFO *qi;
    238  1.1  alc 	uint32_t cwMin, chanCwMin, value;
    239  1.1  alc 
    240  1.1  alc 	if (q >= HAL_NUM_TX_QUEUES) {
    241  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n",
    242  1.1  alc 		    __func__, q);
    243  1.1  alc 		return AH_FALSE;
    244  1.1  alc 	}
    245  1.1  alc 	qi = &ahp->ah_txq[q];
    246  1.1  alc 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
    247  1.1  alc 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: inactive queue %u\n",
    248  1.1  alc 		    __func__, q);
    249  1.1  alc 		return AH_TRUE;		/* XXX??? */
    250  1.1  alc 	}
    251  1.1  alc 
    252  1.1  alc 	if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) {
    253  1.1  alc 		/*
    254  1.1  alc 		 * Select cwmin according to channel type.
    255  1.1  alc 		 * NB: chan can be NULL during attach
    256  1.1  alc 		 */
    257  1.1  alc 		if (chan && IS_CHAN_B(chan))
    258  1.1  alc 			chanCwMin = INIT_CWMIN_11B;
    259  1.1  alc 		else
    260  1.1  alc 			chanCwMin = INIT_CWMIN;
    261  1.1  alc 		/* make sure that the CWmin is of the form (2^n - 1) */
    262  1.1  alc 		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1)
    263  1.1  alc 			;
    264  1.1  alc 	} else
    265  1.1  alc 		cwMin = qi->tqi_cwmin;
    266  1.1  alc 
    267  1.1  alc 	/* set cwMin/Max and AIFS values */
    268  1.1  alc 	OS_REG_WRITE(ah, AR_DLCL_IFS(q),
    269  1.1  alc 		  SM(cwMin, AR_D_LCL_IFS_CWMIN)
    270  1.1  alc 		| SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
    271  1.1  alc 		| SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
    272  1.1  alc 
    273  1.1  alc 	/* Set retry limit values */
    274  1.1  alc 	OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q),
    275  1.1  alc 		   SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
    276  1.1  alc 		 | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
    277  1.1  alc 		 | SM(qi->tqi_lgretry, AR_D_RETRY_LIMIT_FR_LG)
    278  1.1  alc 		 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
    279  1.1  alc 	);
    280  1.1  alc 
    281  1.1  alc 	/* enable early termination on the QCU */
    282  1.1  alc 	OS_REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
    283  1.1  alc 
    284  1.1  alc 	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
    285  1.1  alc 		/* Configure DCU to use the global sequence count */
    286  1.1  alc 		OS_REG_WRITE(ah, AR_DMISC(q), AR5311_D_MISC_SEQ_NUM_CONTROL);
    287  1.1  alc 	}
    288  1.1  alc 	/* multiqueue support */
    289  1.1  alc 	if (qi->tqi_cbrPeriod) {
    290  1.1  alc 		OS_REG_WRITE(ah, AR_QCBRCFG(q),
    291  1.1  alc 			  SM(qi->tqi_cbrPeriod,AR_Q_CBRCFG_CBR_INTERVAL)
    292  1.1  alc 			| SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_CBR_OVF_THRESH));
    293  1.1  alc 		OS_REG_WRITE(ah, AR_QMISC(q),
    294  1.1  alc 			OS_REG_READ(ah, AR_QMISC(q)) |
    295  1.1  alc 			AR_Q_MISC_FSP_CBR |
    296  1.1  alc 			(qi->tqi_cbrOverflowLimit ?
    297  1.1  alc 				AR_Q_MISC_CBR_EXP_CNTR_LIMIT : 0));
    298  1.1  alc 	}
    299  1.1  alc 	if (qi->tqi_readyTime) {
    300  1.1  alc 		OS_REG_WRITE(ah, AR_QRDYTIMECFG(q),
    301  1.1  alc 			SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) |
    302  1.1  alc 			AR_Q_RDYTIMECFG_EN);
    303  1.1  alc 	}
    304  1.1  alc 	if (qi->tqi_burstTime) {
    305  1.1  alc 		OS_REG_WRITE(ah, AR_DCHNTIME(q),
    306  1.1  alc 			SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
    307  1.1  alc 			AR_D_CHNTIME_EN);
    308  1.1  alc 		if (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE) {
    309  1.1  alc 			OS_REG_WRITE(ah, AR_QMISC(q),
    310  1.1  alc 			     OS_REG_READ(ah, AR_QMISC(q)) |
    311  1.1  alc 			     AR_Q_MISC_RDYTIME_EXP_POLICY);
    312  1.1  alc 		}
    313  1.1  alc 	}
    314  1.1  alc 
    315  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) {
    316  1.1  alc 		OS_REG_WRITE(ah, AR_DMISC(q),
    317  1.1  alc 			OS_REG_READ(ah, AR_DMISC(q)) |
    318  1.1  alc 			AR_D_MISC_POST_FR_BKOFF_DIS);
    319  1.1  alc 	}
    320  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) {
    321  1.1  alc 		OS_REG_WRITE(ah, AR_DMISC(q),
    322  1.1  alc 			OS_REG_READ(ah, AR_DMISC(q)) |
    323  1.1  alc 			AR_D_MISC_FRAG_BKOFF_EN);
    324  1.1  alc 	}
    325  1.1  alc 	switch (qi->tqi_type) {
    326  1.1  alc 	case HAL_TX_QUEUE_BEACON:
    327  1.1  alc 		/* Configure QCU for beacons */
    328  1.1  alc 		OS_REG_WRITE(ah, AR_QMISC(q),
    329  1.1  alc 			OS_REG_READ(ah, AR_QMISC(q))
    330  1.1  alc 			| AR_Q_MISC_FSP_DBA_GATED
    331  1.1  alc 			| AR_Q_MISC_BEACON_USE
    332  1.1  alc 			| AR_Q_MISC_CBR_INCR_DIS1);
    333  1.1  alc 		/* Configure DCU for beacons */
    334  1.1  alc 		value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
    335  1.1  alc 			| AR_D_MISC_BEACON_USE | AR_D_MISC_POST_FR_BKOFF_DIS;
    336  1.1  alc 		if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
    337  1.1  alc 			value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
    338  1.1  alc 		OS_REG_WRITE(ah, AR_DMISC(q), value);
    339  1.1  alc 		break;
    340  1.1  alc 	case HAL_TX_QUEUE_CAB:
    341  1.1  alc 		/* Configure QCU for CAB (Crap After Beacon) frames */
    342  1.1  alc 		OS_REG_WRITE(ah, AR_QMISC(q),
    343  1.1  alc 			OS_REG_READ(ah, AR_QMISC(q))
    344  1.1  alc 			| AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1
    345  1.1  alc 			| AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY);
    346  1.1  alc 
    347  1.1  alc 		value = (ahp->ah_beaconInterval
    348  1.1  alc 			- (ath_hal_sw_beacon_response_time - ath_hal_dma_beacon_response_time)
    349  1.1  alc 			- ath_hal_additional_swba_backoff) * 1024;
    350  1.1  alc 		OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN);
    351  1.1  alc 
    352  1.1  alc 		/* Configure DCU for CAB */
    353  1.1  alc 		value = (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S);
    354  1.1  alc 		if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU)
    355  1.1  alc 			value |= AR5311_D_MISC_SEQ_NUM_CONTROL;
    356  1.1  alc 		OS_REG_WRITE(ah, AR_QMISC(q), value);
    357  1.1  alc 		break;
    358  1.1  alc 	default:
    359  1.1  alc 		/* NB: silence compiler */
    360  1.1  alc 		break;
    361  1.1  alc 	}
    362  1.1  alc 
    363  1.1  alc 	/*
    364  1.1  alc 	 * Always update the secondary interrupt mask registers - this
    365  1.1  alc 	 * could be a new queue getting enabled in a running system or
    366  1.1  alc 	 * hw getting re-initialized during a reset!
    367  1.1  alc 	 *
    368  1.1  alc 	 * Since we don't differentiate between tx interrupts corresponding
    369  1.1  alc 	 * to individual queues - secondary tx mask regs are always unmasked;
    370  1.1  alc 	 * tx interrupts are enabled/disabled for all queues collectively
    371  1.1  alc 	 * using the primary mask reg
    372  1.1  alc 	 */
    373  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE)
    374  1.1  alc 		ahp->ah_txOkInterruptMask |= 1 << q;
    375  1.1  alc 	else
    376  1.1  alc 		ahp->ah_txOkInterruptMask &= ~(1 << q);
    377  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE)
    378  1.1  alc 		ahp->ah_txErrInterruptMask |= 1 << q;
    379  1.1  alc 	else
    380  1.1  alc 		ahp->ah_txErrInterruptMask &= ~(1 << q);
    381  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)
    382  1.1  alc 		ahp->ah_txDescInterruptMask |= 1 << q;
    383  1.1  alc 	else
    384  1.1  alc 		ahp->ah_txDescInterruptMask &= ~(1 << q);
    385  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)
    386  1.1  alc 		ahp->ah_txEolInterruptMask |= 1 << q;
    387  1.1  alc 	else
    388  1.1  alc 		ahp->ah_txEolInterruptMask &= ~(1 << q);
    389  1.1  alc 	if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)
    390  1.1  alc 		ahp->ah_txUrnInterruptMask |= 1 << q;
    391  1.1  alc 	else
    392  1.1  alc 		ahp->ah_txUrnInterruptMask &= ~(1 << q);
    393  1.1  alc 	setTxQInterrupts(ah, qi);
    394  1.1  alc 
    395  1.1  alc 	return AH_TRUE;
    396  1.1  alc }
    397  1.1  alc 
    398  1.1  alc /*
    399  1.1  alc  * Get the TXDP for the specified data queue.
    400  1.1  alc  */
    401  1.1  alc uint32_t
    402  1.1  alc ar5211GetTxDP(struct ath_hal *ah, u_int q)
    403  1.1  alc {
    404  1.1  alc 	HALASSERT(q < HAL_NUM_TX_QUEUES);
    405  1.1  alc 	return OS_REG_READ(ah, AR_QTXDP(q));
    406  1.1  alc }
    407  1.1  alc 
    408  1.1  alc /*
    409  1.1  alc  * Set the TxDP for the specified tx queue.
    410  1.1  alc  */
    411  1.1  alc HAL_BOOL
    412  1.1  alc ar5211SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp)
    413  1.1  alc {
    414  1.1  alc 	HALASSERT(q < HAL_NUM_TX_QUEUES);
    415  1.1  alc 	HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
    416  1.1  alc 
    417  1.1  alc 	/*
    418  1.1  alc 	 * Make sure that TXE is deasserted before setting the TXDP.  If TXE
    419  1.1  alc 	 * is still asserted, setting TXDP will have no effect.
    420  1.1  alc 	 */
    421  1.1  alc 	HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0);
    422  1.1  alc 
    423  1.1  alc 	OS_REG_WRITE(ah, AR_QTXDP(q), txdp);
    424  1.1  alc 
    425  1.1  alc 	return AH_TRUE;
    426  1.1  alc }
    427  1.1  alc 
    428  1.1  alc /*
    429  1.1  alc  * Set Transmit Enable bits for the specified queues.
    430  1.1  alc  */
    431  1.1  alc HAL_BOOL
    432  1.1  alc ar5211StartTxDma(struct ath_hal *ah, u_int q)
    433  1.1  alc {
    434  1.1  alc 	HALASSERT(q < HAL_NUM_TX_QUEUES);
    435  1.1  alc 	HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
    436  1.1  alc 
    437  1.1  alc 	/* Check that queue is not already active */
    438  1.1  alc 	HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1<<q)) == 0);
    439  1.1  alc 
    440  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);
    441  1.1  alc 
    442  1.1  alc 	/* Check to be sure we're not enabling a q that has its TXD bit set. */
    443  1.1  alc 	HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0);
    444  1.1  alc 
    445  1.1  alc 	OS_REG_WRITE(ah, AR_Q_TXE, 1 << q);
    446  1.1  alc 	return AH_TRUE;
    447  1.1  alc }
    448  1.1  alc 
    449  1.1  alc /*
    450  1.1  alc  * Return the number of frames pending on the specified queue.
    451  1.1  alc  */
    452  1.1  alc uint32_t
    453  1.1  alc ar5211NumTxPending(struct ath_hal *ah, u_int q)
    454  1.1  alc {
    455  1.1  alc 	uint32_t n;
    456  1.1  alc 
    457  1.1  alc 	HALASSERT(q < HAL_NUM_TX_QUEUES);
    458  1.1  alc 	HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
    459  1.1  alc 
    460  1.1  alc 	n = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT_M;
    461  1.1  alc 	/*
    462  1.1  alc 	 * Pending frame count (PFC) can momentarily go to zero
    463  1.1  alc 	 * while TXE remains asserted.  In other words a PFC of
    464  1.1  alc 	 * zero is not sufficient to say that the queue has stopped.
    465  1.1  alc 	 */
    466  1.1  alc 	if (n == 0 && (OS_REG_READ(ah, AR_Q_TXE) & (1<<q)))
    467  1.1  alc 		n = 1;			/* arbitrarily pick 1 */
    468  1.1  alc 	return n;
    469  1.1  alc }
    470  1.1  alc 
    471  1.1  alc /*
    472  1.1  alc  * Stop transmit on the specified queue
    473  1.1  alc  */
    474  1.1  alc HAL_BOOL
    475  1.1  alc ar5211StopTxDma(struct ath_hal *ah, u_int q)
    476  1.1  alc {
    477  1.1  alc 	int i;
    478  1.1  alc 
    479  1.1  alc 	HALASSERT(q < HAL_NUM_TX_QUEUES);
    480  1.1  alc 	HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
    481  1.1  alc 
    482  1.1  alc 	OS_REG_WRITE(ah, AR_Q_TXD, 1<<q);
    483  1.1  alc 	for (i = 0; i < 10000; i++) {
    484  1.1  alc 		if (ar5211NumTxPending(ah, q) == 0)
    485  1.1  alc 			break;
    486  1.1  alc 		OS_DELAY(10);
    487  1.1  alc 	}
    488  1.1  alc 	OS_REG_WRITE(ah, AR_Q_TXD, 0);
    489  1.1  alc 
    490  1.1  alc 	return (i < 10000);
    491  1.1  alc }
    492  1.1  alc 
    493  1.1  alc /*
    494  1.1  alc  * Descriptor Access Functions
    495  1.1  alc  */
    496  1.1  alc 
    497  1.1  alc #define	VALID_PKT_TYPES \
    498  1.1  alc 	((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
    499  1.1  alc 	 (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
    500  1.1  alc 	 (1<<HAL_PKT_TYPE_BEACON))
    501  1.1  alc #define	isValidPktType(_t)	((1<<(_t)) & VALID_PKT_TYPES)
    502  1.1  alc #define	VALID_TX_RATES \
    503  1.1  alc 	((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
    504  1.1  alc 	 (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
    505  1.1  alc 	 (1<<0x1d)|(1<<0x18)|(1<<0x1c))
    506  1.1  alc #define	isValidTxRate(_r)	((1<<(_r)) & VALID_TX_RATES)
    507  1.1  alc 
    508  1.1  alc HAL_BOOL
    509  1.1  alc ar5211SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
    510  1.1  alc 	u_int pktLen,
    511  1.1  alc 	u_int hdrLen,
    512  1.1  alc 	HAL_PKT_TYPE type,
    513  1.1  alc 	u_int txPower,
    514  1.1  alc 	u_int txRate0, u_int txTries0,
    515  1.1  alc 	u_int keyIx,
    516  1.1  alc 	u_int antMode,
    517  1.1  alc 	u_int flags,
    518  1.1  alc 	u_int rtsctsRate,
    519  1.1  alc 	u_int rtsctsDuration,
    520  1.1  alc 	u_int compicvLen,
    521  1.1  alc 	u_int compivLen,
    522  1.1  alc 	u_int comp)
    523  1.1  alc {
    524  1.1  alc 	struct ar5211_desc *ads = AR5211DESC(ds);
    525  1.1  alc 
    526  1.1  alc 	(void) hdrLen;
    527  1.1  alc 	(void) txPower;
    528  1.1  alc 	(void) rtsctsRate; (void) rtsctsDuration;
    529  1.1  alc 
    530  1.1  alc 	HALASSERT(txTries0 != 0);
    531  1.1  alc 	HALASSERT(isValidPktType(type));
    532  1.1  alc 	HALASSERT(isValidTxRate(txRate0));
    533  1.1  alc 	/* XXX validate antMode */
    534  1.1  alc 
    535  1.1  alc 	ads->ds_ctl0 = (pktLen & AR_FrameLen)
    536  1.1  alc 		     | (txRate0 << AR_XmitRate_S)
    537  1.1  alc 		     | (antMode << AR_AntModeXmit_S)
    538  1.1  alc 		     | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0)
    539  1.1  alc 		     | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0)
    540  1.1  alc 		     | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0)
    541  1.1  alc 		     | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
    542  1.1  alc 		     ;
    543  1.1  alc 	ads->ds_ctl1 = (type << 26)
    544  1.1  alc 		     | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
    545  1.1  alc 		     ;
    546  1.1  alc 
    547  1.1  alc 	if (keyIx != HAL_TXKEYIX_INVALID) {
    548  1.1  alc 		ads->ds_ctl1 |=
    549  1.1  alc 			(keyIx << AR_EncryptKeyIdx_S) & AR_EncryptKeyIdx;
    550  1.1  alc 		ads->ds_ctl0 |= AR_EncryptKeyValid;
    551  1.1  alc 	}
    552  1.1  alc 	return AH_TRUE;
    553  1.1  alc #undef RATE
    554  1.1  alc }
    555  1.1  alc 
    556  1.1  alc HAL_BOOL
    557  1.1  alc ar5211SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
    558  1.1  alc 	u_int txRate1, u_int txTries1,
    559  1.1  alc 	u_int txRate2, u_int txTries2,
    560  1.1  alc 	u_int txRate3, u_int txTries3)
    561  1.1  alc {
    562  1.1  alc 	(void) ah; (void) ds;
    563  1.1  alc 	(void) txRate1; (void) txTries1;
    564  1.1  alc 	(void) txRate2; (void) txTries2;
    565  1.1  alc 	(void) txRate3; (void) txTries3;
    566  1.1  alc 	return AH_FALSE;
    567  1.1  alc }
    568  1.1  alc 
    569  1.1  alc void
    570  1.1  alc ar5211IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds)
    571  1.1  alc {
    572  1.1  alc 	struct ar5211_desc *ads = AR5211DESC(ds);
    573  1.1  alc 
    574  1.1  alc 	ads->ds_ctl0 |= AR_TxInterReq;
    575  1.1  alc }
    576  1.1  alc 
    577  1.1  alc HAL_BOOL
    578  1.1  alc ar5211FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
    579  1.1  alc 	u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
    580  1.1  alc 	const struct ath_desc *ds0)
    581  1.1  alc {
    582  1.1  alc 	struct ar5211_desc *ads = AR5211DESC(ds);
    583  1.1  alc 
    584  1.1  alc 	HALASSERT((segLen &~ AR_BufLen) == 0);
    585  1.1  alc 
    586  1.1  alc 	if (firstSeg) {
    587  1.1  alc 		/*
    588  1.1  alc 		 * First descriptor, don't clobber xmit control data
    589  1.1  alc 		 * setup by ar5211SetupTxDesc.
    590  1.1  alc 		 */
    591  1.1  alc 		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More);
    592  1.1  alc 	} else if (lastSeg) {		/* !firstSeg && lastSeg */
    593  1.1  alc 		/*
    594  1.1  alc 		 * Last descriptor in a multi-descriptor frame,
    595  1.1  alc 		 * copy the transmit parameters from the first
    596  1.1  alc 		 * frame for processing on completion.
    597  1.1  alc 		 */
    598  1.1  alc 		ads->ds_ctl0 = AR5211DESC_CONST(ds0)->ds_ctl0;
    599  1.1  alc 		ads->ds_ctl1 = segLen;
    600  1.1  alc 	} else {			/* !firstSeg && !lastSeg */
    601  1.1  alc 		/*
    602  1.1  alc 		 * Intermediate descriptor in a multi-descriptor frame.
    603  1.1  alc 		 */
    604  1.1  alc 		ads->ds_ctl0 = 0;
    605  1.1  alc 		ads->ds_ctl1 = segLen | AR_More;
    606  1.1  alc 	}
    607  1.1  alc 	ads->ds_status0 = ads->ds_status1 = 0;
    608  1.1  alc 	return AH_TRUE;
    609  1.1  alc }
    610  1.1  alc 
    611  1.1  alc /*
    612  1.1  alc  * Processing of HW TX descriptor.
    613  1.1  alc  */
    614  1.1  alc HAL_STATUS
    615  1.1  alc ar5211ProcTxDesc(struct ath_hal *ah,
    616  1.1  alc 	struct ath_desc *ds, struct ath_tx_status *ts)
    617  1.1  alc {
    618  1.1  alc 	struct ar5211_desc *ads = AR5211DESC(ds);
    619  1.1  alc 
    620  1.1  alc 	if ((ads->ds_status1 & AR_Done) == 0)
    621  1.1  alc 		return HAL_EINPROGRESS;
    622  1.1  alc 
    623  1.1  alc 	/* Update software copies of the HW status */
    624  1.1  alc 	ts->ts_seqnum = MS(ads->ds_status1, AR_SeqNum);
    625  1.1  alc 	ts->ts_tstamp = MS(ads->ds_status0, AR_SendTimestamp);
    626  1.1  alc 	ts->ts_status = 0;
    627  1.1  alc 	if ((ads->ds_status0 & AR_FrmXmitOK) == 0) {
    628  1.1  alc 		if (ads->ds_status0 & AR_ExcessiveRetries)
    629  1.1  alc 			ts->ts_status |= HAL_TXERR_XRETRY;
    630  1.1  alc 		if (ads->ds_status0 & AR_Filtered)
    631  1.1  alc 			ts->ts_status |= HAL_TXERR_FILT;
    632  1.1  alc 		if (ads->ds_status0 & AR_FIFOUnderrun)
    633  1.1  alc 			ts->ts_status |= HAL_TXERR_FIFO;
    634  1.1  alc 	}
    635  1.1  alc 	ts->ts_rate = MS(ads->ds_ctl0, AR_XmitRate);
    636  1.1  alc 	ts->ts_rssi = MS(ads->ds_status1, AR_AckSigStrength);
    637  1.1  alc 	ts->ts_shortretry = MS(ads->ds_status0, AR_ShortRetryCnt);
    638  1.1  alc 	ts->ts_longretry = MS(ads->ds_status0, AR_LongRetryCnt);
    639  1.1  alc 	ts->ts_virtcol = MS(ads->ds_status0, AR_VirtCollCnt);
    640  1.1  alc 	ts->ts_antenna = 0;		/* NB: don't know */
    641  1.1  alc 	ts->ts_finaltsi = 0;
    642  1.1  alc 	/*
    643  1.1  alc 	 * NB: the number of retries is one less than it should be.
    644  1.1  alc 	 * Also, 0 retries and 1 retry are both reported as 0 retries.
    645  1.1  alc 	 */
    646  1.1  alc 	if (ts->ts_shortretry > 0)
    647  1.1  alc 		ts->ts_shortretry++;
    648  1.1  alc 	if (ts->ts_longretry > 0)
    649  1.1  alc 		ts->ts_longretry++;
    650  1.1  alc 
    651  1.1  alc 	return HAL_OK;
    652  1.1  alc }
    653  1.1  alc 
    654  1.1  alc /*
    655  1.1  alc  * Determine which tx queues need interrupt servicing.
    656  1.1  alc  * STUB.
    657  1.1  alc  */
    658  1.1  alc void
    659  1.1  alc ar5211GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs)
    660  1.1  alc {
    661  1.1  alc 	return;
    662  1.1  alc }
    663