1*1e10b93dSalc /*
2*1e10b93dSalc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3*1e10b93dSalc  * Copyright (c) 2002-2008 Atheros Communications, Inc.
4*1e10b93dSalc  *
5*1e10b93dSalc  * Permission to use, copy, modify, and/or distribute this software for any
6*1e10b93dSalc  * purpose with or without fee is hereby granted, provided that the above
7*1e10b93dSalc  * copyright notice and this permission notice appear in all copies.
8*1e10b93dSalc  *
9*1e10b93dSalc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*1e10b93dSalc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*1e10b93dSalc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*1e10b93dSalc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*1e10b93dSalc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*1e10b93dSalc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*1e10b93dSalc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*1e10b93dSalc  *
17*1e10b93dSalc  * $Id: ar5416_xmit.c,v 1.1.1.1 2008/12/11 04:46:50 alc Exp $
18*1e10b93dSalc  */
19*1e10b93dSalc #include "opt_ah.h"
20*1e10b93dSalc 
21*1e10b93dSalc #include "ah.h"
22*1e10b93dSalc #include "ah_desc.h"
23*1e10b93dSalc #include "ah_internal.h"
24*1e10b93dSalc 
25*1e10b93dSalc #include "ar5416/ar5416.h"
26*1e10b93dSalc #include "ar5416/ar5416reg.h"
27*1e10b93dSalc #include "ar5416/ar5416phy.h"
28*1e10b93dSalc #include "ar5416/ar5416desc.h"
29*1e10b93dSalc 
30*1e10b93dSalc /*
31*1e10b93dSalc  * Stop transmit on the specified queue
32*1e10b93dSalc  */
33*1e10b93dSalc HAL_BOOL
ar5416StopTxDma(struct ath_hal * ah,u_int q)34*1e10b93dSalc ar5416StopTxDma(struct ath_hal *ah, u_int q)
35*1e10b93dSalc {
36*1e10b93dSalc #define	STOP_DMA_TIMEOUT	4000	/* us */
37*1e10b93dSalc #define	STOP_DMA_ITER		100	/* us */
38*1e10b93dSalc 	u_int i;
39*1e10b93dSalc 
40*1e10b93dSalc 	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
41*1e10b93dSalc 
42*1e10b93dSalc 	HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
43*1e10b93dSalc 
44*1e10b93dSalc 	OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
45*1e10b93dSalc 	for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
46*1e10b93dSalc 		if (ar5212NumTxPending(ah, q) == 0)
47*1e10b93dSalc 			break;
48*1e10b93dSalc 		OS_DELAY(STOP_DMA_ITER);
49*1e10b93dSalc 	}
50*1e10b93dSalc #ifdef AH_DEBUG
51*1e10b93dSalc 	if (i == 0) {
52*1e10b93dSalc 		HALDEBUG(ah, HAL_DEBUG_ANY,
53*1e10b93dSalc 		    "%s: queue %u DMA did not stop in 400 msec\n", __func__, q);
54*1e10b93dSalc 		HALDEBUG(ah, HAL_DEBUG_ANY,
55*1e10b93dSalc 		    "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__,
56*1e10b93dSalc 		    OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE),
57*1e10b93dSalc 		    OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q)));
58*1e10b93dSalc 		HALDEBUG(ah, HAL_DEBUG_ANY,
59*1e10b93dSalc 		    "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",
60*1e10b93dSalc 		    __func__, OS_REG_READ(ah, AR_QMISC(q)),
61*1e10b93dSalc 		    OS_REG_READ(ah, AR_QRDYTIMECFG(q)),
62*1e10b93dSalc 		    OS_REG_READ(ah, AR_Q_RDYTIMESHDN));
63*1e10b93dSalc 	}
64*1e10b93dSalc #endif /* AH_DEBUG */
65*1e10b93dSalc 
66*1e10b93dSalc 	/* ar5416 and up can kill packets at the PCU level */
67*1e10b93dSalc 	if (ar5212NumTxPending(ah, q)) {
68*1e10b93dSalc 		uint32_t j;
69*1e10b93dSalc 
70*1e10b93dSalc 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
71*1e10b93dSalc 		    "%s: Num of pending TX Frames %d on Q %d\n",
72*1e10b93dSalc 		    __func__, ar5212NumTxPending(ah, q), q);
73*1e10b93dSalc 
74*1e10b93dSalc 		/* Kill last PCU Tx Frame */
75*1e10b93dSalc 		/* TODO - save off and restore current values of Q1/Q2? */
76*1e10b93dSalc 		for (j = 0; j < 2; j++) {
77*1e10b93dSalc 			uint32_t tsfLow = OS_REG_READ(ah, AR_TSF_L32);
78*1e10b93dSalc 			OS_REG_WRITE(ah, AR_QUIET2,
79*1e10b93dSalc 			    SM(10, AR_QUIET2_QUIET_DUR));
80*1e10b93dSalc 			OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100);
81*1e10b93dSalc 			OS_REG_WRITE(ah, AR_NEXT_QUIET, tsfLow >> 10);
82*1e10b93dSalc 			OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
83*1e10b93dSalc 
84*1e10b93dSalc 			if ((OS_REG_READ(ah, AR_TSF_L32)>>10) == (tsfLow>>10))
85*1e10b93dSalc 				break;
86*1e10b93dSalc 
87*1e10b93dSalc 			HALDEBUG(ah, HAL_DEBUG_ANY,
88*1e10b93dSalc 			    "%s: TSF moved while trying to set quiet time "
89*1e10b93dSalc 			    "TSF: 0x%08x\n", __func__, tsfLow);
90*1e10b93dSalc 			HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */
91*1e10b93dSalc 		}
92*1e10b93dSalc 
93*1e10b93dSalc 		OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
94*1e10b93dSalc 
95*1e10b93dSalc 		/* Allow the quiet mechanism to do its work */
96*1e10b93dSalc 		OS_DELAY(200);
97*1e10b93dSalc 		OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
98*1e10b93dSalc 
99*1e10b93dSalc 		/* Verify the transmit q is empty */
100*1e10b93dSalc 		for (i = STOP_DMA_TIMEOUT/STOP_DMA_ITER; i != 0; i--) {
101*1e10b93dSalc 			if (ar5212NumTxPending(ah, q) == 0)
102*1e10b93dSalc 				break;
103*1e10b93dSalc 			OS_DELAY(STOP_DMA_ITER);
104*1e10b93dSalc 		}
105*1e10b93dSalc 		if (i == 0) {
106*1e10b93dSalc 			HALDEBUG(ah, HAL_DEBUG_ANY,
107*1e10b93dSalc 			    "%s: Failed to stop Tx DMA in %d msec after killing"
108*1e10b93dSalc 			    " last frame\n", __func__, STOP_DMA_TIMEOUT / 1000);
109*1e10b93dSalc 		}
110*1e10b93dSalc 		OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);
111*1e10b93dSalc 	}
112*1e10b93dSalc 
113*1e10b93dSalc 	OS_REG_WRITE(ah, AR_Q_TXD, 0);
114*1e10b93dSalc 	return (i != 0);
115*1e10b93dSalc #undef STOP_DMA_ITER
116*1e10b93dSalc #undef STOP_DMA_TIMEOUT
117*1e10b93dSalc }
118*1e10b93dSalc 
119*1e10b93dSalc #define VALID_KEY_TYPES \
120*1e10b93dSalc         ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\
121*1e10b93dSalc          (1 << HAL_KEY_TYPE_AES)   | (1 << HAL_KEY_TYPE_TKIP))
122*1e10b93dSalc #define isValidKeyType(_t)      ((1 << (_t)) & VALID_KEY_TYPES)
123*1e10b93dSalc 
124*1e10b93dSalc #define set11nTries(_series, _index) \
125*1e10b93dSalc         (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
126*1e10b93dSalc 
127*1e10b93dSalc #define set11nRate(_series, _index) \
128*1e10b93dSalc         (SM((_series)[_index].Rate, AR_XmitRate##_index))
129*1e10b93dSalc 
130*1e10b93dSalc #define set11nPktDurRTSCTS(_series, _index) \
131*1e10b93dSalc         (SM((_series)[_index].PktDuration, AR_PacketDur##_index) |\
132*1e10b93dSalc          ((_series)[_index].RateFlags & HAL_RATESERIES_RTS_CTS   ?\
133*1e10b93dSalc          AR_RTSCTSQual##_index : 0))
134*1e10b93dSalc 
135*1e10b93dSalc #define set11nRateFlags(_series, _index) \
136*1e10b93dSalc         ((_series)[_index].RateFlags & HAL_RATESERIES_2040 ? AR_2040_##_index : 0) \
137*1e10b93dSalc         |((_series)[_index].RateFlags & HAL_RATESERIES_HALFGI ? AR_GI##_index : 0) \
138*1e10b93dSalc         |SM((_series)[_index].ChSel, AR_ChainSel##_index)
139*1e10b93dSalc 
140*1e10b93dSalc /*
141*1e10b93dSalc  * Descriptor Access Functions
142*1e10b93dSalc  */
143*1e10b93dSalc 
144*1e10b93dSalc #define VALID_PKT_TYPES \
145*1e10b93dSalc         ((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\
146*1e10b93dSalc          (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\
147*1e10b93dSalc          (1<<HAL_PKT_TYPE_BEACON)|(1<<HAL_PKT_TYPE_AMPDU))
148*1e10b93dSalc #define isValidPktType(_t)      ((1<<(_t)) & VALID_PKT_TYPES)
149*1e10b93dSalc #define VALID_TX_RATES \
150*1e10b93dSalc         ((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\
151*1e10b93dSalc          (1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\
152*1e10b93dSalc          (1<<0x1d)|(1<<0x18)|(1<<0x1c))
153*1e10b93dSalc #define isValidTxRate(_r)       ((1<<(_r)) & VALID_TX_RATES)
154*1e10b93dSalc 
155*1e10b93dSalc HAL_BOOL
ar5416SetupTxDesc(struct ath_hal * ah,struct ath_desc * ds,u_int pktLen,u_int hdrLen,HAL_PKT_TYPE type,u_int txPower,u_int txRate0,u_int txTries0,u_int keyIx,u_int antMode,u_int flags,u_int rtsctsRate,u_int rtsctsDuration,u_int compicvLen,u_int compivLen,u_int comp)156*1e10b93dSalc ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
157*1e10b93dSalc 	u_int pktLen,
158*1e10b93dSalc 	u_int hdrLen,
159*1e10b93dSalc 	HAL_PKT_TYPE type,
160*1e10b93dSalc 	u_int txPower,
161*1e10b93dSalc 	u_int txRate0, u_int txTries0,
162*1e10b93dSalc 	u_int keyIx,
163*1e10b93dSalc 	u_int antMode,
164*1e10b93dSalc 	u_int flags,
165*1e10b93dSalc 	u_int rtsctsRate,
166*1e10b93dSalc 	u_int rtsctsDuration,
167*1e10b93dSalc 	u_int compicvLen,
168*1e10b93dSalc 	u_int compivLen,
169*1e10b93dSalc 	u_int comp)
170*1e10b93dSalc {
171*1e10b93dSalc #define	RTSCTS	(HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
172*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
173*1e10b93dSalc 	struct ath_hal_5416 *ahp = AH5416(ah);
174*1e10b93dSalc 
175*1e10b93dSalc 	(void) hdrLen;
176*1e10b93dSalc 
177*1e10b93dSalc 	HALASSERT(txTries0 != 0);
178*1e10b93dSalc 	HALASSERT(isValidPktType(type));
179*1e10b93dSalc 	HALASSERT(isValidTxRate(txRate0));
180*1e10b93dSalc 	HALASSERT((flags & RTSCTS) != RTSCTS);
181*1e10b93dSalc 	/* XXX validate antMode */
182*1e10b93dSalc 
183*1e10b93dSalc         txPower = (txPower + AH5212(ah)->ah_txPowerIndexOffset);
184*1e10b93dSalc         if (txPower > 63)
185*1e10b93dSalc 		txPower = 63;
186*1e10b93dSalc 
187*1e10b93dSalc 	ads->ds_ctl0 = (pktLen & AR_FrameLen)
188*1e10b93dSalc 		     | (txPower << AR_XmitPower_S)
189*1e10b93dSalc 		     | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
190*1e10b93dSalc 		     | (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
191*1e10b93dSalc 		     | (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0)
192*1e10b93dSalc 		     ;
193*1e10b93dSalc 	ads->ds_ctl1 = (type << AR_FrameType_S)
194*1e10b93dSalc 		     | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0)
195*1e10b93dSalc                      ;
196*1e10b93dSalc 	ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0)
197*1e10b93dSalc 		     | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEn : 0)
198*1e10b93dSalc 		     ;
199*1e10b93dSalc 	ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S)
200*1e10b93dSalc 		     ;
201*1e10b93dSalc 	ads->ds_ctl4 = 0;
202*1e10b93dSalc 	ads->ds_ctl5 = 0;
203*1e10b93dSalc 	ads->ds_ctl6 = 0;
204*1e10b93dSalc 	ads->ds_ctl7 = SM(ahp->ah_tx_chainmask, AR_ChainSel0)
205*1e10b93dSalc 		     | SM(ahp->ah_tx_chainmask, AR_ChainSel1)
206*1e10b93dSalc 		     | SM(ahp->ah_tx_chainmask, AR_ChainSel2)
207*1e10b93dSalc 		     | SM(ahp->ah_tx_chainmask, AR_ChainSel3)
208*1e10b93dSalc 		     ;
209*1e10b93dSalc 	ads->ds_ctl8 = 0;
210*1e10b93dSalc 	ads->ds_ctl9 = (txPower << 24);		/* XXX? */
211*1e10b93dSalc 	ads->ds_ctl10 = (txPower << 24);	/* XXX? */
212*1e10b93dSalc 	ads->ds_ctl11 = (txPower << 24);	/* XXX? */
213*1e10b93dSalc 	if (keyIx != HAL_TXKEYIX_INVALID) {
214*1e10b93dSalc 		/* XXX validate key index */
215*1e10b93dSalc 		ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
216*1e10b93dSalc 		ads->ds_ctl0 |= AR_DestIdxValid;
217*1e10b93dSalc 		ads->ds_ctl6 |= SM(ahp->ah_keytype[keyIx], AR_EncrType);
218*1e10b93dSalc 	}
219*1e10b93dSalc 	if (flags & RTSCTS) {
220*1e10b93dSalc 		if (!isValidTxRate(rtsctsRate)) {
221*1e10b93dSalc 			HALDEBUG(ah, HAL_DEBUG_ANY,
222*1e10b93dSalc 			    "%s: invalid rts/cts rate 0x%x\n",
223*1e10b93dSalc 			    __func__, rtsctsRate);
224*1e10b93dSalc 			return AH_FALSE;
225*1e10b93dSalc 		}
226*1e10b93dSalc 		/* XXX validate rtsctsDuration */
227*1e10b93dSalc 		ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
228*1e10b93dSalc 			     | (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0)
229*1e10b93dSalc 			     ;
230*1e10b93dSalc 		ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
231*1e10b93dSalc 		ads->ds_ctl7 |= (rtsctsRate << AR_RTSCTSRate_S);
232*1e10b93dSalc 	}
233*1e10b93dSalc 	return AH_TRUE;
234*1e10b93dSalc #undef RTSCTS
235*1e10b93dSalc }
236*1e10b93dSalc 
237*1e10b93dSalc HAL_BOOL
ar5416SetupXTxDesc(struct ath_hal * ah,struct ath_desc * ds,u_int txRate1,u_int txTries1,u_int txRate2,u_int txTries2,u_int txRate3,u_int txTries3)238*1e10b93dSalc ar5416SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds,
239*1e10b93dSalc 	u_int txRate1, u_int txTries1,
240*1e10b93dSalc 	u_int txRate2, u_int txTries2,
241*1e10b93dSalc 	u_int txRate3, u_int txTries3)
242*1e10b93dSalc {
243*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
244*1e10b93dSalc 
245*1e10b93dSalc 	if (txTries1) {
246*1e10b93dSalc 		HALASSERT(isValidTxRate(txRate1));
247*1e10b93dSalc 		ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1);
248*1e10b93dSalc 		ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S);
249*1e10b93dSalc 	}
250*1e10b93dSalc 	if (txTries2) {
251*1e10b93dSalc 		HALASSERT(isValidTxRate(txRate2));
252*1e10b93dSalc 		ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2);
253*1e10b93dSalc 		ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S);
254*1e10b93dSalc 	}
255*1e10b93dSalc 	if (txTries3) {
256*1e10b93dSalc 		HALASSERT(isValidTxRate(txRate3));
257*1e10b93dSalc 		ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3);
258*1e10b93dSalc 		ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S);
259*1e10b93dSalc 	}
260*1e10b93dSalc 	return AH_TRUE;
261*1e10b93dSalc }
262*1e10b93dSalc 
263*1e10b93dSalc HAL_BOOL
ar5416FillTxDesc(struct ath_hal * ah,struct ath_desc * ds,u_int segLen,HAL_BOOL firstSeg,HAL_BOOL lastSeg,const struct ath_desc * ds0)264*1e10b93dSalc ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds,
265*1e10b93dSalc 	u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg,
266*1e10b93dSalc 	const struct ath_desc *ds0)
267*1e10b93dSalc {
268*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
269*1e10b93dSalc 
270*1e10b93dSalc 	HALASSERT((segLen &~ AR_BufLen) == 0);
271*1e10b93dSalc 
272*1e10b93dSalc 	if (firstSeg) {
273*1e10b93dSalc 		/*
274*1e10b93dSalc 		 * First descriptor, don't clobber xmit control data
275*1e10b93dSalc 		 * setup by ar5212SetupTxDesc.
276*1e10b93dSalc 		 */
277*1e10b93dSalc 		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
278*1e10b93dSalc 	} else if (lastSeg) {		/* !firstSeg && lastSeg */
279*1e10b93dSalc 		/*
280*1e10b93dSalc 		 * Last descriptor in a multi-descriptor frame,
281*1e10b93dSalc 		 * copy the multi-rate transmit parameters from
282*1e10b93dSalc 		 * the first frame for processing on completion.
283*1e10b93dSalc 		 */
284*1e10b93dSalc 		ads->ds_ctl0 = 0;
285*1e10b93dSalc 		ads->ds_ctl1 = segLen;
286*1e10b93dSalc #ifdef AH_NEED_DESC_SWAP
287*1e10b93dSalc 		ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
288*1e10b93dSalc 		ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
289*1e10b93dSalc #else
290*1e10b93dSalc 		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
291*1e10b93dSalc 		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
292*1e10b93dSalc #endif
293*1e10b93dSalc 	} else {			/* !firstSeg && !lastSeg */
294*1e10b93dSalc 		/*
295*1e10b93dSalc 		 * Intermediate descriptor in a multi-descriptor frame.
296*1e10b93dSalc 		 */
297*1e10b93dSalc 		ads->ds_ctl0 = 0;
298*1e10b93dSalc 		ads->ds_ctl1 = segLen | AR_TxMore;
299*1e10b93dSalc 		ads->ds_ctl2 = 0;
300*1e10b93dSalc 		ads->ds_ctl3 = 0;
301*1e10b93dSalc 	}
302*1e10b93dSalc 	/* XXX only on last descriptor? */
303*1e10b93dSalc 	OS_MEMZERO(ads->u.tx.status, sizeof(ads->u.tx.status));
304*1e10b93dSalc 	return AH_TRUE;
305*1e10b93dSalc }
306*1e10b93dSalc 
307*1e10b93dSalc #if 0
308*1e10b93dSalc 
309*1e10b93dSalc HAL_BOOL
310*1e10b93dSalc ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds,
311*1e10b93dSalc 	u_int pktLen,
312*1e10b93dSalc 	u_int hdrLen,
313*1e10b93dSalc 	HAL_PKT_TYPE type,
314*1e10b93dSalc 	u_int keyIx,
315*1e10b93dSalc 	HAL_CIPHER cipher,
316*1e10b93dSalc 	uint8_t delims,
317*1e10b93dSalc 	u_int segLen,
318*1e10b93dSalc 	HAL_BOOL firstSeg,
319*1e10b93dSalc 	HAL_BOOL lastSeg)
320*1e10b93dSalc {
321*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
322*1e10b93dSalc 	uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
323*1e10b93dSalc 
324*1e10b93dSalc 	int isaggr = 0;
325*1e10b93dSalc 
326*1e10b93dSalc 	(void) hdrLen;
327*1e10b93dSalc 	(void) ah;
328*1e10b93dSalc 
329*1e10b93dSalc 	HALASSERT((segLen &~ AR_BufLen) == 0);
330*1e10b93dSalc 
331*1e10b93dSalc 	HALASSERT(isValidPktType(type));
332*1e10b93dSalc 	if (type == HAL_PKT_TYPE_AMPDU) {
333*1e10b93dSalc 		type = HAL_PKT_TYPE_NORMAL;
334*1e10b93dSalc 		isaggr = 1;
335*1e10b93dSalc 	}
336*1e10b93dSalc 
337*1e10b93dSalc 	if (!firstSeg) {
338*1e10b93dSalc 		ath_hal_memzero(ds->ds_hw, AR5416_DESC_TX_CTL_SZ);
339*1e10b93dSalc 	}
340*1e10b93dSalc 
341*1e10b93dSalc 	ads->ds_ctl0 = (pktLen & AR_FrameLen);
342*1e10b93dSalc 	ads->ds_ctl1 = (type << AR_FrameType_S)
343*1e10b93dSalc 			| (isaggr ? (AR_IsAggr | AR_MoreAggr) : 0);
344*1e10b93dSalc 	ads->ds_ctl2 = 0;
345*1e10b93dSalc 	ads->ds_ctl3 = 0;
346*1e10b93dSalc 	if (keyIx != HAL_TXKEYIX_INVALID) {
347*1e10b93dSalc 		/* XXX validate key index */
348*1e10b93dSalc 		ads->ds_ctl1 |= SM(keyIx, AR_DestIdx);
349*1e10b93dSalc 		ads->ds_ctl0 |= AR_DestIdxValid;
350*1e10b93dSalc 	}
351*1e10b93dSalc 
352*1e10b93dSalc 	ads->ds_ctl6 = SM(keyType[cipher], AR_EncrType);
353*1e10b93dSalc 	if (isaggr) {
354*1e10b93dSalc 		ads->ds_ctl6 |= SM(delims, AR_PadDelim);
355*1e10b93dSalc 	}
356*1e10b93dSalc 
357*1e10b93dSalc 	if (firstSeg) {
358*1e10b93dSalc 		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
359*1e10b93dSalc 	} else if (lastSeg) {           /* !firstSeg && lastSeg */
360*1e10b93dSalc 		ads->ds_ctl0 = 0;
361*1e10b93dSalc 		ads->ds_ctl1 |= segLen;
362*1e10b93dSalc 	} else {                        /* !firstSeg && !lastSeg */
363*1e10b93dSalc 		/*
364*1e10b93dSalc 		 * Intermediate descriptor in a multi-descriptor frame.
365*1e10b93dSalc 		 */
366*1e10b93dSalc 		ads->ds_ctl0 = 0;
367*1e10b93dSalc 		ads->ds_ctl1 |= segLen | AR_TxMore;
368*1e10b93dSalc 	}
369*1e10b93dSalc 	ds_txstatus[0] = ds_txstatus[1] = 0;
370*1e10b93dSalc 	ds_txstatus[9] &= ~AR_TxDone;
371*1e10b93dSalc 
372*1e10b93dSalc 	return AH_TRUE;
373*1e10b93dSalc }
374*1e10b93dSalc 
375*1e10b93dSalc HAL_BOOL
376*1e10b93dSalc ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds,
377*1e10b93dSalc 	u_int aggrLen, u_int flags, u_int txPower,
378*1e10b93dSalc 	u_int txRate0, u_int txTries0, u_int antMode,
379*1e10b93dSalc 	u_int rtsctsRate, u_int rtsctsDuration)
380*1e10b93dSalc {
381*1e10b93dSalc #define RTSCTS  (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)
382*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
383*1e10b93dSalc 	struct ath_hal_5212 *ahp = AH5212(ah);
384*1e10b93dSalc 
385*1e10b93dSalc 	HALASSERT(txTries0 != 0);
386*1e10b93dSalc 	HALASSERT(isValidTxRate(txRate0));
387*1e10b93dSalc 	HALASSERT((flags & RTSCTS) != RTSCTS);
388*1e10b93dSalc 	/* XXX validate antMode */
389*1e10b93dSalc 
390*1e10b93dSalc 	txPower = (txPower + ahp->ah_txPowerIndexOffset );
391*1e10b93dSalc 	if(txPower > 63)  txPower=63;
392*1e10b93dSalc 
393*1e10b93dSalc 	ads->ds_ctl0 |= (txPower << AR_XmitPower_S)
394*1e10b93dSalc 		| (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
395*1e10b93dSalc 		| (flags & HAL_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
396*1e10b93dSalc 		| (flags & HAL_TXDESC_INTREQ ? AR_TxIntrReq : 0);
397*1e10b93dSalc 	ads->ds_ctl1 |= (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0);
398*1e10b93dSalc 	ads->ds_ctl2 |= SM(txTries0, AR_XmitDataTries0);
399*1e10b93dSalc 	ads->ds_ctl3 |= (txRate0 << AR_XmitRate0_S);
400*1e10b93dSalc 	ads->ds_ctl7 = SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel0)
401*1e10b93dSalc 		| SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1)
402*1e10b93dSalc 		| SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2)
403*1e10b93dSalc 		| SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3);
404*1e10b93dSalc 
405*1e10b93dSalc 	/* NB: no V1 WAR */
406*1e10b93dSalc 	ads->ds_ctl8 = 0;
407*1e10b93dSalc 	ads->ds_ctl9 = (txPower << 24);
408*1e10b93dSalc 	ads->ds_ctl10 = (txPower << 24);
409*1e10b93dSalc 	ads->ds_ctl11 = (txPower << 24);
410*1e10b93dSalc 
411*1e10b93dSalc 	ads->ds_ctl6 &= ~(0xffff);
412*1e10b93dSalc 	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
413*1e10b93dSalc 
414*1e10b93dSalc 	if (flags & RTSCTS) {
415*1e10b93dSalc 		/* XXX validate rtsctsDuration */
416*1e10b93dSalc 		ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0)
417*1e10b93dSalc 			| (flags & HAL_TXDESC_RTSENA ? AR_RTSEnable : 0);
418*1e10b93dSalc 		ads->ds_ctl2 |= SM(rtsctsDuration, AR_BurstDur);
419*1e10b93dSalc 	}
420*1e10b93dSalc 
421*1e10b93dSalc 	return AH_TRUE;
422*1e10b93dSalc #undef RTSCTS
423*1e10b93dSalc }
424*1e10b93dSalc 
425*1e10b93dSalc HAL_BOOL
426*1e10b93dSalc ar5416SetupLastTxDesc(struct ath_hal *ah, struct ath_desc *ds,
427*1e10b93dSalc 		const struct ath_desc *ds0)
428*1e10b93dSalc {
429*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
430*1e10b93dSalc 
431*1e10b93dSalc 	ads->ds_ctl1 &= ~AR_MoreAggr;
432*1e10b93dSalc 	ads->ds_ctl6 &= ~AR_PadDelim;
433*1e10b93dSalc 
434*1e10b93dSalc 	/* hack to copy rate info to last desc for later processing */
435*1e10b93dSalc #ifdef AH_NEED_DESC_SWAP
436*1e10b93dSalc 	ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2);
437*1e10b93dSalc 	ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3);
438*1e10b93dSalc #else
439*1e10b93dSalc 	ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
440*1e10b93dSalc 	ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
441*1e10b93dSalc #endif
442*1e10b93dSalc 
443*1e10b93dSalc 	return AH_TRUE;
444*1e10b93dSalc }
445*1e10b93dSalc #endif /* 0 */
446*1e10b93dSalc 
447*1e10b93dSalc #ifdef AH_NEED_DESC_SWAP
448*1e10b93dSalc /* Swap transmit descriptor */
449*1e10b93dSalc static __inline void
ar5416SwapTxDesc(struct ath_desc * ds)450*1e10b93dSalc ar5416SwapTxDesc(struct ath_desc *ds)
451*1e10b93dSalc {
452*1e10b93dSalc 	ds->ds_data = __bswap32(ds->ds_data);
453*1e10b93dSalc 	ds->ds_ctl0 = __bswap32(ds->ds_ctl0);
454*1e10b93dSalc 	ds->ds_ctl1 = __bswap32(ds->ds_ctl1);
455*1e10b93dSalc 	ds->ds_hw[0] = __bswap32(ds->ds_hw[0]);
456*1e10b93dSalc 	ds->ds_hw[1] = __bswap32(ds->ds_hw[1]);
457*1e10b93dSalc 	ds->ds_hw[2] = __bswap32(ds->ds_hw[2]);
458*1e10b93dSalc 	ds->ds_hw[3] = __bswap32(ds->ds_hw[3]);
459*1e10b93dSalc }
460*1e10b93dSalc #endif
461*1e10b93dSalc 
462*1e10b93dSalc /*
463*1e10b93dSalc  * Processing of HW TX descriptor.
464*1e10b93dSalc  */
465*1e10b93dSalc HAL_STATUS
ar5416ProcTxDesc(struct ath_hal * ah,struct ath_desc * ds,struct ath_tx_status * ts)466*1e10b93dSalc ar5416ProcTxDesc(struct ath_hal *ah,
467*1e10b93dSalc 	struct ath_desc *ds, struct ath_tx_status *ts)
468*1e10b93dSalc {
469*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
470*1e10b93dSalc 	uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
471*1e10b93dSalc 
472*1e10b93dSalc #ifdef AH_NEED_DESC_SWAP
473*1e10b93dSalc 	if ((ds_txstatus[9] & __bswap32(AR_TxDone)) == 0)
474*1e10b93dSalc 		return HAL_EINPROGRESS;
475*1e10b93dSalc 	ar5416SwapTxDesc(ds);
476*1e10b93dSalc #else
477*1e10b93dSalc 	if ((ds_txstatus[9] & AR_TxDone) == 0)
478*1e10b93dSalc 		return HAL_EINPROGRESS;
479*1e10b93dSalc #endif
480*1e10b93dSalc 
481*1e10b93dSalc 	/* Update software copies of the HW status */
482*1e10b93dSalc 	ts->ts_seqnum = MS(ds_txstatus[9], AR_SeqNum);
483*1e10b93dSalc 	ts->ts_tstamp = AR_SendTimestamp(ds_txstatus);
484*1e10b93dSalc 
485*1e10b93dSalc 	ts->ts_status = 0;
486*1e10b93dSalc 	if (ds_txstatus[1] & AR_ExcessiveRetries)
487*1e10b93dSalc 		ts->ts_status |= HAL_TXERR_XRETRY;
488*1e10b93dSalc 	if (ds_txstatus[1] & AR_Filtered)
489*1e10b93dSalc 		ts->ts_status |= HAL_TXERR_FILT;
490*1e10b93dSalc 	if (ds_txstatus[1] & AR_FIFOUnderrun)
491*1e10b93dSalc 		ts->ts_status |= HAL_TXERR_FIFO;
492*1e10b93dSalc 	if (ds_txstatus[9] & AR_TxOpExceeded)
493*1e10b93dSalc 		ts->ts_status |= HAL_TXERR_XTXOP;
494*1e10b93dSalc 	if (ds_txstatus[1] & AR_TxTimerExpired)
495*1e10b93dSalc 		ts->ts_status |= HAL_TXERR_TIMER_EXPIRED;
496*1e10b93dSalc 
497*1e10b93dSalc 	ts->ts_flags  = 0;
498*1e10b93dSalc 	if (ds_txstatus[0] & AR_TxBaStatus) {
499*1e10b93dSalc 		ts->ts_flags |= HAL_TX_BA;
500*1e10b93dSalc 		ts->ts_ba_low = AR_BaBitmapLow(ds_txstatus);
501*1e10b93dSalc 		ts->ts_ba_high = AR_BaBitmapHigh(ds_txstatus);
502*1e10b93dSalc 	}
503*1e10b93dSalc 	if (ds->ds_ctl1 & AR_IsAggr)
504*1e10b93dSalc 		ts->ts_flags |= HAL_TX_AGGR;
505*1e10b93dSalc 	if (ds_txstatus[1] & AR_DescCfgErr)
506*1e10b93dSalc 		ts->ts_flags |= HAL_TX_DESC_CFG_ERR;
507*1e10b93dSalc 	if (ds_txstatus[1] & AR_TxDataUnderrun)
508*1e10b93dSalc 		ts->ts_flags |= HAL_TX_DATA_UNDERRUN;
509*1e10b93dSalc 	if (ds_txstatus[1] & AR_TxDelimUnderrun)
510*1e10b93dSalc 		ts->ts_flags |= HAL_TX_DELIM_UNDERRUN;
511*1e10b93dSalc 
512*1e10b93dSalc 	/*
513*1e10b93dSalc 	 * Extract the transmit rate used and mark the rate as
514*1e10b93dSalc 	 * ``alternate'' if it wasn't the series 0 rate.
515*1e10b93dSalc 	 */
516*1e10b93dSalc 	ts->ts_finaltsi =  MS(ds_txstatus[9], AR_FinalTxIdx);
517*1e10b93dSalc 	switch (ts->ts_finaltsi) {
518*1e10b93dSalc 	case 0:
519*1e10b93dSalc 		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0);
520*1e10b93dSalc 		break;
521*1e10b93dSalc 	case 1:
522*1e10b93dSalc 		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) |
523*1e10b93dSalc 			HAL_TXSTAT_ALTRATE;
524*1e10b93dSalc 		break;
525*1e10b93dSalc 	case 2:
526*1e10b93dSalc 		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) |
527*1e10b93dSalc 			HAL_TXSTAT_ALTRATE;
528*1e10b93dSalc 		break;
529*1e10b93dSalc 	case 3:
530*1e10b93dSalc 		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) |
531*1e10b93dSalc 			HAL_TXSTAT_ALTRATE;
532*1e10b93dSalc 		break;
533*1e10b93dSalc 	}
534*1e10b93dSalc 
535*1e10b93dSalc 	ts->ts_rssi = MS(ds_txstatus[5], AR_TxRSSICombined);
536*1e10b93dSalc 	ts->ts_rssi_ctl[0] = MS(ds_txstatus[0], AR_TxRSSIAnt00);
537*1e10b93dSalc 	ts->ts_rssi_ctl[1] = MS(ds_txstatus[0], AR_TxRSSIAnt01);
538*1e10b93dSalc 	ts->ts_rssi_ctl[2] = MS(ds_txstatus[0], AR_TxRSSIAnt02);
539*1e10b93dSalc 	ts->ts_rssi_ext[0] = MS(ds_txstatus[5], AR_TxRSSIAnt10);
540*1e10b93dSalc 	ts->ts_rssi_ext[1] = MS(ds_txstatus[5], AR_TxRSSIAnt11);
541*1e10b93dSalc 	ts->ts_rssi_ext[2] = MS(ds_txstatus[5], AR_TxRSSIAnt12);
542*1e10b93dSalc 	ts->ts_evm0 = AR_TxEVM0(ds_txstatus);
543*1e10b93dSalc 	ts->ts_evm1 = AR_TxEVM1(ds_txstatus);
544*1e10b93dSalc 	ts->ts_evm2 = AR_TxEVM2(ds_txstatus);
545*1e10b93dSalc 
546*1e10b93dSalc 	ts->ts_shortretry = MS(ds_txstatus[1], AR_RTSFailCnt);
547*1e10b93dSalc 	ts->ts_longretry = MS(ds_txstatus[1], AR_DataFailCnt);
548*1e10b93dSalc 	/*
549*1e10b93dSalc 	 * The retry count has the number of un-acked tries for the
550*1e10b93dSalc 	 * final series used.  When doing multi-rate retry we must
551*1e10b93dSalc 	 * fixup the retry count by adding in the try counts for
552*1e10b93dSalc 	 * each series that was fully-processed.  Beware that this
553*1e10b93dSalc 	 * takes values from the try counts in the final descriptor.
554*1e10b93dSalc 	 * These are not required by the hardware.  We assume they
555*1e10b93dSalc 	 * are placed there by the driver as otherwise we have no
556*1e10b93dSalc 	 * access and the driver can't do the calculation because it
557*1e10b93dSalc 	 * doesn't know the descriptor format.
558*1e10b93dSalc 	 */
559*1e10b93dSalc 	switch (ts->ts_finaltsi) {
560*1e10b93dSalc 	case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2);
561*1e10b93dSalc 	case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1);
562*1e10b93dSalc 	case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0);
563*1e10b93dSalc 	}
564*1e10b93dSalc 
565*1e10b93dSalc 	/*
566*1e10b93dSalc 	 * These fields are not used. Zero these to preserve compatability
567*1e10b93dSalc 	 * with existing drivers.
568*1e10b93dSalc 	 */
569*1e10b93dSalc 	ts->ts_virtcol = MS(ads->ds_ctl1, AR_VirtRetryCnt);
570*1e10b93dSalc 	ts->ts_antenna = 0; /* We don't switch antennas on Owl*/
571*1e10b93dSalc 
572*1e10b93dSalc 	/* handle tx trigger level changes internally */
573*1e10b93dSalc 	if ((ts->ts_status & HAL_TXERR_FIFO) ||
574*1e10b93dSalc 	    (ts->ts_flags & (HAL_TX_DATA_UNDERRUN | HAL_TX_DELIM_UNDERRUN)))
575*1e10b93dSalc 		ar5212UpdateTxTrigLevel(ah, AH_TRUE);
576*1e10b93dSalc 
577*1e10b93dSalc 	return HAL_OK;
578*1e10b93dSalc }
579*1e10b93dSalc 
580*1e10b93dSalc #if 0
581*1e10b93dSalc HAL_BOOL
582*1e10b93dSalc ar5416SetGlobalTxTimeout(struct ath_hal *ah, u_int tu)
583*1e10b93dSalc {
584*1e10b93dSalc 	struct ath_hal_5416 *ahp = AH5416(ah);
585*1e10b93dSalc 
586*1e10b93dSalc 	if (tu > 0xFFFF) {
587*1e10b93dSalc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad global tx timeout %u\n",
588*1e10b93dSalc 		    __func__, tu);
589*1e10b93dSalc 		/* restore default handling */
590*1e10b93dSalc 		ahp->ah_globaltxtimeout = (u_int) -1;
591*1e10b93dSalc 		return AH_FALSE;
592*1e10b93dSalc 	}
593*1e10b93dSalc 	OS_REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
594*1e10b93dSalc 	ahp->ah_globaltxtimeout = tu;
595*1e10b93dSalc 	return AH_TRUE;
596*1e10b93dSalc }
597*1e10b93dSalc 
598*1e10b93dSalc u_int
599*1e10b93dSalc ar5416GetGlobalTxTimeout(struct ath_hal *ah)
600*1e10b93dSalc {
601*1e10b93dSalc 	return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT);
602*1e10b93dSalc }
603*1e10b93dSalc 
604*1e10b93dSalc void
605*1e10b93dSalc ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds,
606*1e10b93dSalc         u_int durUpdateEn, u_int rtsctsRate,
607*1e10b93dSalc 	HAL_11N_RATE_SERIES series[], u_int nseries)
608*1e10b93dSalc {
609*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
610*1e10b93dSalc 
611*1e10b93dSalc 	HALASSERT(nseries == 4);
612*1e10b93dSalc 	(void)nseries;
613*1e10b93dSalc 
614*1e10b93dSalc 
615*1e10b93dSalc 	ads->ds_ctl2 = set11nTries(series, 0)
616*1e10b93dSalc 		     | set11nTries(series, 1)
617*1e10b93dSalc 		     | set11nTries(series, 2)
618*1e10b93dSalc 		     | set11nTries(series, 3)
619*1e10b93dSalc 		     | (durUpdateEn ? AR_DurUpdateEn : 0);
620*1e10b93dSalc 
621*1e10b93dSalc 	ads->ds_ctl3 = set11nRate(series, 0)
622*1e10b93dSalc 		     | set11nRate(series, 1)
623*1e10b93dSalc 		     | set11nRate(series, 2)
624*1e10b93dSalc 		     | set11nRate(series, 3);
625*1e10b93dSalc 
626*1e10b93dSalc 	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
627*1e10b93dSalc 		     | set11nPktDurRTSCTS(series, 1);
628*1e10b93dSalc 
629*1e10b93dSalc 	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
630*1e10b93dSalc 		     | set11nPktDurRTSCTS(series, 3);
631*1e10b93dSalc 
632*1e10b93dSalc 	ads->ds_ctl7 = set11nRateFlags(series, 0)
633*1e10b93dSalc 		     | set11nRateFlags(series, 1)
634*1e10b93dSalc 		     | set11nRateFlags(series, 2)
635*1e10b93dSalc 		     | set11nRateFlags(series, 3)
636*1e10b93dSalc 		     | SM(rtsctsRate, AR_RTSCTSRate);
637*1e10b93dSalc 
638*1e10b93dSalc 	/*
639*1e10b93dSalc 	 * Enable RTSCTS if any of the series is flagged for RTSCTS,
640*1e10b93dSalc 	 * but only if CTS is not enabled.
641*1e10b93dSalc 	 */
642*1e10b93dSalc 	/*
643*1e10b93dSalc 	 * FIXME : the entire RTS/CTS handling should be moved to this
644*1e10b93dSalc 	 * function (by passing the global RTS/CTS flags to this function).
645*1e10b93dSalc 	 * currently it is split between this function and the
646*1e10b93dSalc 	 * setupFiirstDescriptor. with this current implementation there
647*1e10b93dSalc 	 * is an implicit assumption that setupFirstDescriptor is called
648*1e10b93dSalc 	 * before this function.
649*1e10b93dSalc 	 */
650*1e10b93dSalc 	if (((series[0].RateFlags & HAL_RATESERIES_RTS_CTS) ||
651*1e10b93dSalc 	     (series[1].RateFlags & HAL_RATESERIES_RTS_CTS) ||
652*1e10b93dSalc 	     (series[2].RateFlags & HAL_RATESERIES_RTS_CTS) ||
653*1e10b93dSalc 	     (series[3].RateFlags & HAL_RATESERIES_RTS_CTS) )  &&
654*1e10b93dSalc 	    (ads->ds_ctl0 & AR_CTSEnable) == 0) {
655*1e10b93dSalc 		ads->ds_ctl0 |= AR_RTSEnable;
656*1e10b93dSalc 		ads->ds_ctl0 &= ~AR_CTSEnable;
657*1e10b93dSalc 	}
658*1e10b93dSalc }
659*1e10b93dSalc 
660*1e10b93dSalc void
661*1e10b93dSalc ar5416Set11nAggrMiddle(struct ath_hal *ah, struct ath_desc *ds, u_int numDelims)
662*1e10b93dSalc {
663*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
664*1e10b93dSalc 	uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads);
665*1e10b93dSalc 
666*1e10b93dSalc 	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
667*1e10b93dSalc 
668*1e10b93dSalc 	ads->ds_ctl6 &= ~AR_PadDelim;
669*1e10b93dSalc 	ads->ds_ctl6 |= SM(numDelims, AR_PadDelim);
670*1e10b93dSalc 	ads->ds_ctl6 &= ~AR_AggrLen;
671*1e10b93dSalc 
672*1e10b93dSalc 	/*
673*1e10b93dSalc 	 * Clear the TxDone status here, may need to change
674*1e10b93dSalc 	 * func name to reflect this
675*1e10b93dSalc 	 */
676*1e10b93dSalc 	ds_txstatus[9] &= ~AR_TxDone;
677*1e10b93dSalc }
678*1e10b93dSalc 
679*1e10b93dSalc void
680*1e10b93dSalc ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds)
681*1e10b93dSalc {
682*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
683*1e10b93dSalc 
684*1e10b93dSalc 	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
685*1e10b93dSalc 	ads->ds_ctl6 &= ~AR_PadDelim;
686*1e10b93dSalc 	ads->ds_ctl6 &= ~AR_AggrLen;
687*1e10b93dSalc }
688*1e10b93dSalc 
689*1e10b93dSalc void
690*1e10b93dSalc ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds,
691*1e10b93dSalc                                                   u_int burstDuration)
692*1e10b93dSalc {
693*1e10b93dSalc 	struct ar5416_desc *ads = AR5416DESC(ds);
694*1e10b93dSalc 
695*1e10b93dSalc 	ads->ds_ctl2 &= ~AR_BurstDur;
696*1e10b93dSalc 	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
697*1e10b93dSalc }
698*1e10b93dSalc #endif
699