xref: /illumos-gate/usr/src/uts/common/io/arn/arn_mac.c (revision 7ab4e62e3b5c454f248a38bec0d489e8f5543324)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2008 Atheros Communications Inc.
8  *
9  * Permission to use, copy, modify, and/or distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/ddi.h>
23 
24 #include "arn_core.h"
25 #include "arn_hw.h"
26 #include "arn_reg.h"
27 #include "arn_phy.h"
28 
29 /* ARGSUSED */
30 static void
31 ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
32     struct ath9k_tx_queue_info *qi)
33 {
34 	struct ath_hal_5416 *ahp = AH5416(ah);
35 
36 	ARN_DBG((ARN_DBG_INTERRUPT,
37 	    "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
38 	    __func__, ahp->ah_txOkInterruptMask,
39 	    ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
40 	    ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask));
41 
42 	REG_WRITE(ah, AR_IMR_S0,
43 	    SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) |
44 	    SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
45 	REG_WRITE(ah, AR_IMR_S1,
46 	    SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)|
47 	    SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
48 	REG_RMW_FIELD(ah, AR_IMR_S2,
49 	    AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
50 }
51 
52 void
53 ath9k_hw_dmaRegDump(struct ath_hal *ah)
54 {
55 	uint32_t val[ATH9K_NUM_DMA_DEBUG_REGS];
56 	int qcuOffset = 0, dcuOffset = 0;
57 	uint32_t *qcuBase = &val[0], *dcuBase = &val[4];
58 	int i;
59 
60 	REG_WRITE(ah, AR_MACMISC,
61 	    ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
62 	    (AR_MACMISC_MISC_OBS_BUS_1 <<
63 	    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
64 
65 	ARN_DBG((ARN_DBG_REG_IO, "Raw DMA Debug values:\n"));
66 
67 	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
68 		if (i % 4 == 0)
69 			ARN_DBG((ARN_DBG_REG_IO, "\n"));
70 
71 		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof (uint32_t)));
72 		ARN_DBG((ARN_DBG_REG_IO, "%d: %08x ", i, val[i]));
73 	}
74 
75 	ARN_DBG((ARN_DBG_REG_IO, "\n\n"));
76 	ARN_DBG((ARN_DBG_REG_IO,
77 	    "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"));
78 
79 	for (i = 0; i < ATH9K_NUM_QUEUES;
80 	    i++, qcuOffset += 4, dcuOffset += 5) {
81 		if (i == 8) {
82 			qcuOffset = 0;
83 			qcuBase++;
84 		}
85 
86 		if (i == 6) {
87 			dcuOffset = 0;
88 			dcuBase++;
89 		}
90 
91 		ARN_DBG((ARN_DBG_REG_IO,
92 		    "%2d          %2x      %1x     %2x           %2x\n",
93 		    i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
94 		    (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
95 		    val[2] & (0x7 << (i * 3)) >> (i * 3),
96 		    (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset));
97 	}
98 
99 	ARN_DBG((ARN_DBG_REG_IO, "\n"));
100 	ARN_DBG((ARN_DBG_REG_IO,
101 	    "qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
102 	    (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22));
103 	ARN_DBG((ARN_DBG_REG_IO,
104 	    "qcu_complete state: %2x    dcu_complete state:     %2x\n",
105 	    (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)));
106 	ARN_DBG((ARN_DBG_REG_IO,
107 	    "dcu_arb state:      %2x    dcu_fp state:           %2x\n",
108 	    (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27));
109 	ARN_DBG((ARN_DBG_REG_IO,
110 	    "chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
111 	    (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10));
112 	ARN_DBG((ARN_DBG_REG_IO,
113 	    "txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
114 	    (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12));
115 	ARN_DBG((ARN_DBG_REG_IO,
116 	    "txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
117 	    (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17));
118 
119 	ARN_DBG((ARN_DBG_REG_IO, "pcu observe 0x%x \n",
120 	    REG_READ(ah, AR_OBS_BUS_1)));
121 	ARN_DBG((ARN_DBG_REG_IO,
122 	    "AR_CR 0x%x \n", REG_READ(ah, AR_CR)));
123 }
124 
125 uint32_t
126 ath9k_hw_gettxbuf(struct ath_hal *ah, uint32_t q)
127 {
128 	return (REG_READ(ah, AR_QTXDP(q)));
129 }
130 
131 boolean_t
132 ath9k_hw_puttxbuf(struct ath_hal *ah, uint32_t q, uint32_t txdp)
133 {
134 	REG_WRITE(ah, AR_QTXDP(q), txdp);
135 
136 	return (B_TRUE);
137 }
138 
139 boolean_t
140 ath9k_hw_txstart(struct ath_hal *ah, uint32_t q)
141 {
142 	ARN_DBG((ARN_DBG_XMIT, "arn: ath9k_hw_txstart(): "
143 	    "tramist queue is %u\n", q));
144 
145 	REG_WRITE(ah, AR_Q_TXE, 1 << q);
146 
147 	return (B_TRUE);
148 }
149 
150 uint32_t
151 ath9k_hw_numtxpending(struct ath_hal *ah, uint32_t q)
152 {
153 	uint32_t npend;
154 
155 	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
156 	if (npend == 0) {
157 
158 		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
159 			npend = 1;
160 	}
161 
162 	return (npend);
163 }
164 
165 boolean_t
166 ath9k_hw_updatetxtriglevel(struct ath_hal *ah, boolean_t bIncTrigLevel)
167 {
168 	struct ath_hal_5416 *ahp = AH5416(ah);
169 	uint32_t txcfg, curLevel, newLevel;
170 	enum ath9k_int omask;
171 
172 	if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
173 		return (B_FALSE);
174 
175 	omask = ath9k_hw_set_interrupts(ah,
176 	    ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
177 
178 	txcfg = REG_READ(ah, AR_TXCFG);
179 	curLevel = MS(txcfg, AR_FTRIG);
180 	newLevel = curLevel;
181 	if (bIncTrigLevel) {
182 		if (curLevel < MAX_TX_FIFO_THRESHOLD)
183 			newLevel++;
184 	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
185 		newLevel--;
186 	if (newLevel != curLevel)
187 		REG_WRITE(ah, AR_TXCFG,
188 		    (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
189 
190 	(void) ath9k_hw_set_interrupts(ah, omask);
191 
192 	ah->ah_txTrigLevel = (uint16_t)newLevel; /* ??? */
193 
194 	return (newLevel != curLevel);
195 }
196 
197 boolean_t
198 ath9k_hw_stoptxdma(struct ath_hal *ah, uint32_t q)
199 {
200 	uint32_t tsfLow, j, wait;
201 
202 	REG_WRITE(ah, AR_Q_TXD, 1 << q);
203 
204 	for (wait = 1000; wait != 0; wait--) {
205 		if (ath9k_hw_numtxpending(ah, q) == 0)
206 			break;
207 		drv_usecwait(100);
208 	}
209 
210 	if (ath9k_hw_numtxpending(ah, q)) {
211 		ARN_DBG((ARN_DBG_QUEUE,
212 		    "%s: Num of pending TX Frames %d on Q %d\n",
213 		    __func__, ath9k_hw_numtxpending(ah, q), q));
214 
215 		for (j = 0; j < 2; j++) {
216 			tsfLow = REG_READ(ah, AR_TSF_L32);
217 			REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR));
218 			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
219 			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
220 			REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
221 
222 			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
223 				break;
224 			ARN_DBG((ARN_DBG_QUEUE,
225 			    "%s: TSF have moved while trying to set "
226 			    "quiet time TSF: 0x%08x\n",
227 			    __func__, tsfLow));
228 		}
229 
230 		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
231 
232 		drv_usecwait(200);
233 		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
234 
235 		wait = 1000;
236 
237 		while (ath9k_hw_numtxpending(ah, q)) {
238 			if ((--wait) == 0) {
239 				ARN_DBG((ARN_DBG_XMIT,
240 				    "%s: Failed to stop Tx DMA in 100 "
241 				    "msec after killing last frame\n",
242 				    __func__));
243 				break;
244 			}
245 			drv_usecwait(100);
246 		}
247 
248 		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
249 	}
250 
251 	REG_WRITE(ah, AR_Q_TXD, 0);
252 
253 	return (wait != 0);
254 }
255 
256 /* ARGSUSED */
257 boolean_t
258 ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
259     uint32_t segLen, boolean_t firstSeg,
260     boolean_t lastSeg, const struct ath_desc *ds0)
261 {
262 	struct ar5416_desc *ads = AR5416DESC(ds);
263 
264 	if (firstSeg) {
265 		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
266 	} else if (lastSeg) {
267 		ads->ds_ctl0 = 0;
268 		ads->ds_ctl1 = segLen;
269 		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
270 		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
271 	} else {
272 		ads->ds_ctl0 = 0;
273 		ads->ds_ctl1 = segLen | AR_TxMore;
274 		ads->ds_ctl2 = 0;
275 		ads->ds_ctl3 = 0;
276 	}
277 	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
278 	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
279 	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
280 	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
281 	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
282 
283 	return (B_TRUE);
284 }
285 
286 /* ARGSUSED */
287 void
288 ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
289 {
290 	struct ar5416_desc *ads = AR5416DESC(ds);
291 
292 	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
293 	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
294 	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
295 	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
296 	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
297 }
298 
299 int
300 ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
301 {
302 	struct ar5416_desc *ads = AR5416DESC(ds);
303 
304 	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
305 		return (EINPROGRESS);
306 
307 	ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
308 	ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
309 	ds->ds_txstat.ts_status = 0;
310 	ds->ds_txstat.ts_flags = 0;
311 
312 	if (ads->ds_txstatus1 & AR_ExcessiveRetries) {
313 		ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XRETRY\n"));
314 		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
315 	}
316 	if (ads->ds_txstatus1 & AR_Filtered) {
317 		ARN_DBG((ARN_DBG_INTERRUPT, "arn: AR_Filtered\n"));
318 		ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
319 	}
320 	if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
321 		ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_FIFO\n"));
322 		ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
323 		(void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
324 	}
325 	if (ads->ds_txstatus9 & AR_TxOpExceeded) {
326 		ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TXERR_XTXOP\n"));
327 		ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
328 	}
329 	if (ads->ds_txstatus1 & AR_TxTimerExpired) {
330 		ARN_DBG((ARN_DBG_INTERRUPT,
331 		"arn: ATH9K_TXERR_TIMER_EXPIRED\n"));
332 		ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
333 	}
334 
335 	if (ads->ds_txstatus1 & AR_DescCfgErr) {
336 		ARN_DBG((ARN_DBG_INTERRUPT, "arn: ATH9K_TX_DESC_CFG_ERR\n"));
337 		ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
338 	}
339 	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
340 		ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
341 		(void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
342 	}
343 	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
344 		ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
345 		(void) ath9k_hw_updatetxtriglevel(ah, B_TRUE);
346 	}
347 	if (ads->ds_txstatus0 & AR_TxBaStatus) {
348 		ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
349 		ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
350 		ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
351 	}
352 
353 	ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
354 	switch (ds->ds_txstat.ts_rateindex) {
355 	case 0:
356 		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
357 		break;
358 	case 1:
359 		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
360 		break;
361 	case 2:
362 		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
363 		break;
364 	case 3:
365 		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
366 		break;
367 	}
368 
369 	ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
370 	ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
371 	ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
372 	ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
373 	ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
374 	ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
375 	ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
376 	ds->ds_txstat.evm0 = ads->AR_TxEVM0;
377 	ds->ds_txstat.evm1 = ads->AR_TxEVM1;
378 	ds->ds_txstat.evm2 = ads->AR_TxEVM2;
379 	ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
380 	ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
381 	ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
382 	ds->ds_txstat.ts_antenna = 1;
383 
384 	return (0);
385 }
386 
387 void
388 ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
389     uint32_t pktLen, enum ath9k_pkt_type type, uint32_t txPower,
390     uint32_t keyIx, enum ath9k_key_type keyType, uint32_t flags)
391 {
392 	struct ar5416_desc *ads = AR5416DESC(ds);
393 	struct ath_hal_5416 *ahp = AH5416(ah);
394 
395 	txPower += ahp->ah_txPowerIndexOffset;
396 	if (txPower > 63)
397 		txPower = 63;
398 
399 	ads->ds_ctl0 = (pktLen & AR_FrameLen) |
400 	    (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
401 	    SM(txPower, AR_XmitPower) |
402 	    (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
403 	    (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) |
404 	    (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
405 	    (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
406 
407 	ads->ds_ctl1 =
408 	    (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) |
409 	    SM(type, AR_FrameType) |
410 	    (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) |
411 	    (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) |
412 	    (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
413 
414 	ads->ds_ctl6 = SM(keyType, AR_EncrType);
415 
416 	if (AR_SREV_9285(ah)) {
417 		ads->ds_ctl8 = 0;
418 		ads->ds_ctl9 = 0;
419 		ads->ds_ctl10 = 0;
420 		ads->ds_ctl11 = 0;
421 	}
422 
423 }
424 
425 /* ARGSUSED */
426 void
427 ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
428     struct ath_desc *lastds,
429     uint32_t durUpdateEn, uint32_t rtsctsRate,
430     uint32_t rtsctsDuration,
431     struct ath9k_11n_rate_series series[],
432     uint32_t nseries, uint32_t flags)
433 {
434 	struct ar5416_desc *ads = AR5416DESC(ds);
435 	struct ar5416_desc *last_ads = AR5416DESC(lastds);
436 	uint32_t ds_ctl0;
437 
438 	(void) nseries;
439 	(void) rtsctsDuration;
440 
441 	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
442 		ds_ctl0 = ads->ds_ctl0;
443 
444 		if (flags & ATH9K_TXDESC_RTSENA) {
445 			ds_ctl0 &= ~AR_CTSEnable;
446 			ds_ctl0 |= AR_RTSEnable;
447 		} else {
448 			ds_ctl0 &= ~AR_RTSEnable;
449 			ds_ctl0 |= AR_CTSEnable;
450 		}
451 
452 		ads->ds_ctl0 = ds_ctl0;
453 	} else {
454 		ads->ds_ctl0 =
455 		    (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
456 	}
457 
458 	ads->ds_ctl2 = set11nTries(series, 0) |
459 	    set11nTries(series, 1) |
460 	    set11nTries(series, 2) |
461 	    set11nTries(series, 3) |
462 	    (durUpdateEn ? AR_DurUpdateEna : 0) |
463 	    SM(0, AR_BurstDur);
464 
465 	ads->ds_ctl3 = set11nRate(series, 0) |
466 	    set11nRate(series, 1) |
467 	    set11nRate(series, 2) |
468 	    set11nRate(series, 3);
469 
470 	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) |
471 	    set11nPktDurRTSCTS(series, 1);
472 
473 	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) |
474 	    set11nPktDurRTSCTS(series, 3);
475 
476 	ads->ds_ctl7 = set11nRateFlags(series, 0) |
477 	    set11nRateFlags(series, 1) |
478 	    set11nRateFlags(series, 2) |
479 	    set11nRateFlags(series, 3) |
480 	    SM(rtsctsRate, AR_RTSCTSRate);
481 	last_ads->ds_ctl2 = ads->ds_ctl2;
482 	last_ads->ds_ctl3 = ads->ds_ctl3;
483 }
484 
485 /* ARGSUSED */
486 void
487 ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
488     uint32_t aggrLen)
489 {
490 	struct ar5416_desc *ads = AR5416DESC(ds);
491 
492 	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
493 	ads->ds_ctl6 &= ~AR_AggrLen;
494 	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
495 }
496 
497 /* ARGSUSED */
498 void
499 ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
500     uint32_t numDelims)
501 {
502 	struct ar5416_desc *ads = AR5416DESC(ds);
503 	unsigned int ctl6;
504 
505 	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
506 
507 	ctl6 = ads->ds_ctl6;
508 	ctl6 &= ~AR_PadDelim;
509 	ctl6 |= SM(numDelims, AR_PadDelim);
510 	ads->ds_ctl6 = ctl6;
511 }
512 
513 /* ARGSUSED */
514 void
515 ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
516 {
517 	struct ar5416_desc *ads = AR5416DESC(ds);
518 
519 	ads->ds_ctl1 |= AR_IsAggr;
520 	ads->ds_ctl1 &= ~AR_MoreAggr;
521 	ads->ds_ctl6 &= ~AR_PadDelim;
522 }
523 
524 /* ARGSUSED */
525 void
526 ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
527 {
528 	struct ar5416_desc *ads = AR5416DESC(ds);
529 
530 	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
531 }
532 
533 /* ARGSUSED */
534 void
535 ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
536     uint32_t burstDuration)
537 {
538 	struct ar5416_desc *ads = AR5416DESC(ds);
539 
540 	ads->ds_ctl2 &= ~AR_BurstDur;
541 	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
542 }
543 
544 /* ARGSUSED */
545 void
546 ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
547     uint32_t vmf)
548 {
549 	struct ar5416_desc *ads = AR5416DESC(ds);
550 
551 	if (vmf)
552 		ads->ds_ctl0 |= AR_VirtMoreFrag;
553 	else
554 		ads->ds_ctl0 &= ~AR_VirtMoreFrag;
555 }
556 
557 void
558 ath9k_hw_gettxintrtxqs(struct ath_hal *ah, uint32_t *txqs)
559 {
560 	struct ath_hal_5416 *ahp = AH5416(ah);
561 
562 	*txqs &= ahp->ah_intrTxqs;
563 	ahp->ah_intrTxqs &= ~(*txqs);
564 }
565 
566 boolean_t
567 ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
568     const struct ath9k_tx_queue_info *qinfo)
569 {
570 	uint32_t cw;
571 	struct ath_hal_5416 *ahp = AH5416(ah);
572 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
573 	struct ath9k_tx_queue_info *qi;
574 
575 	if (q >= pCap->total_queues) {
576 		ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
577 		    __func__, q));
578 		return (B_FALSE);
579 	}
580 
581 	qi = &ahp->ah_txq[q];
582 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
583 		ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue\n",
584 		    __func__));
585 		return (B_FALSE);
586 	}
587 
588 	ARN_DBG((ARN_DBG_QUEUE, "%s: queue %p\n", __func__, qi));
589 
590 	qi->tqi_ver = qinfo->tqi_ver;
591 	qi->tqi_subtype = qinfo->tqi_subtype;
592 	qi->tqi_qflags = qinfo->tqi_qflags;
593 	qi->tqi_priority = qinfo->tqi_priority;
594 	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
595 		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
596 	else
597 		qi->tqi_aifs = INIT_AIFS;
598 	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
599 		cw = min(qinfo->tqi_cwmin, 1024U);
600 		qi->tqi_cwmin = 1;
601 		while (qi->tqi_cwmin < cw)
602 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
603 	} else
604 		qi->tqi_cwmin = qinfo->tqi_cwmin;
605 	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
606 		cw = min(qinfo->tqi_cwmax, 1024U);
607 		qi->tqi_cwmax = 1;
608 		while (qi->tqi_cwmax < cw)
609 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
610 	} else
611 		qi->tqi_cwmax = INIT_CWMAX;
612 
613 	if (qinfo->tqi_shretry != 0)
614 		qi->tqi_shretry = min((uint32_t)qinfo->tqi_shretry, 15U);
615 	else
616 		qi->tqi_shretry = INIT_SH_RETRY;
617 	if (qinfo->tqi_lgretry != 0)
618 		qi->tqi_lgretry = min((uint32_t)qinfo->tqi_lgretry, 15U);
619 	else
620 		qi->tqi_lgretry = INIT_LG_RETRY;
621 	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
622 	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
623 	qi->tqi_burstTime = qinfo->tqi_burstTime;
624 	qi->tqi_readyTime = qinfo->tqi_readyTime;
625 
626 	switch (qinfo->tqi_subtype) {
627 	case ATH9K_WME_UPSD:
628 		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
629 			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
630 		break;
631 	default:
632 		break;
633 	}
634 
635 	return (B_TRUE);
636 }
637 
638 boolean_t
639 ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
640     struct ath9k_tx_queue_info *qinfo)
641 {
642 	struct ath_hal_5416 *ahp = AH5416(ah);
643 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
644 	struct ath9k_tx_queue_info *qi;
645 
646 	if (q >= pCap->total_queues) {
647 		ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
648 		    "invalid queue num %u\n", q));
649 		return (B_FALSE);
650 	}
651 
652 	qi = &ahp->ah_txq[q];
653 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
654 		ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_get_txq_props(): "
655 		    "inactive queue\n"));
656 		return (B_FALSE);
657 	}
658 
659 	qinfo->tqi_qflags = qi->tqi_qflags;
660 	qinfo->tqi_ver = qi->tqi_ver;
661 	qinfo->tqi_subtype = qi->tqi_subtype;
662 	qinfo->tqi_qflags = qi->tqi_qflags;
663 	qinfo->tqi_priority = qi->tqi_priority;
664 	qinfo->tqi_aifs = qi->tqi_aifs;
665 	qinfo->tqi_cwmin = qi->tqi_cwmin;
666 	qinfo->tqi_cwmax = qi->tqi_cwmax;
667 	qinfo->tqi_shretry = qi->tqi_shretry;
668 	qinfo->tqi_lgretry = qi->tqi_lgretry;
669 	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
670 	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
671 	qinfo->tqi_burstTime = qi->tqi_burstTime;
672 	qinfo->tqi_readyTime = qi->tqi_readyTime;
673 
674 	return (B_TRUE);
675 }
676 
677 int
678 ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
679     const struct ath9k_tx_queue_info *qinfo)
680 {
681 	struct ath_hal_5416 *ahp = AH5416(ah);
682 	struct ath9k_tx_queue_info *qi;
683 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
684 	int q;
685 
686 	switch (type) {
687 	case ATH9K_TX_QUEUE_BEACON:
688 		q = pCap->total_queues - 1;
689 		break;
690 	case ATH9K_TX_QUEUE_CAB:
691 		q = pCap->total_queues - 2;
692 		break;
693 	case ATH9K_TX_QUEUE_PSPOLL:
694 		q = 1;
695 		break;
696 	case ATH9K_TX_QUEUE_UAPSD:
697 		q = pCap->total_queues - 3;
698 		break;
699 	case ATH9K_TX_QUEUE_DATA:
700 		for (q = 0; q < pCap->total_queues; q++)
701 			if (ahp->ah_txq[q].tqi_type ==
702 			    ATH9K_TX_QUEUE_INACTIVE)
703 				break;
704 		if (q == pCap->total_queues) {
705 			ARN_DBG((ARN_DBG_QUEUE,
706 			    "arn: ath9k_hw_setuptxqueue(): "
707 			    "no available tx queue\n"));
708 			return (-1);
709 		}
710 		break;
711 	default:
712 		ARN_DBG((ARN_DBG_QUEUE,
713 		    "arn: ath9k_hw_setuptxqueue(): "
714 		    "bad tx queue type %u\n", type));
715 
716 		return (-1);
717 	}
718 
719 	ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
720 	    "queue %u\n", q));
721 
722 	qi = &ahp->ah_txq[q];
723 	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
724 		ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_setuptxqueue(): "
725 		    "tx queue %u already active\n", q));
726 
727 		return (-1);
728 	}
729 	(void) memset(qi, 0, sizeof (struct ath9k_tx_queue_info));
730 	qi->tqi_type = type;
731 	if (qinfo == NULL) {
732 		qi->tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
733 		    TXQ_FLAG_TXERRINT_ENABLE |
734 		    TXQ_FLAG_TXDESCINT_ENABLE |
735 		    TXQ_FLAG_TXURNINT_ENABLE;
736 		qi->tqi_aifs = INIT_AIFS;
737 		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
738 		qi->tqi_cwmax = INIT_CWMAX;
739 		qi->tqi_shretry = INIT_SH_RETRY;
740 		qi->tqi_lgretry = INIT_LG_RETRY;
741 		qi->tqi_physCompBuf = 0;
742 	} else {
743 		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
744 		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
745 	}
746 
747 	return (q);
748 }
749 
750 boolean_t
751 ath9k_hw_releasetxqueue(struct ath_hal *ah, uint32_t q)
752 {
753 	struct ath_hal_5416 *ahp = AH5416(ah);
754 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
755 	struct ath9k_tx_queue_info *qi;
756 
757 	if (q >= pCap->total_queues) {
758 		ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
759 		    "invalid queue num %u\n", q));
760 		return (B_FALSE);
761 	}
762 	qi = &ahp->ah_txq[q];
763 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
764 		ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
765 		    "inactive queue %u\n", q));
766 		return (B_FALSE);
767 	}
768 
769 	ARN_DBG((ARN_DBG_QUEUE, "arn: arn_txq_setup(): "
770 	    "release queue %u\n", q));
771 
772 
773 	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
774 	ahp->ah_txOkInterruptMask &= ~(1 << q);
775 	ahp->ah_txErrInterruptMask &= ~(1 << q);
776 	ahp->ah_txDescInterruptMask &= ~(1 << q);
777 	ahp->ah_txEolInterruptMask &= ~(1 << q);
778 	ahp->ah_txUrnInterruptMask &= ~(1 << q);
779 	ath9k_hw_set_txq_interrupts(ah, qi);
780 
781 	return (B_TRUE);
782 }
783 
784 boolean_t
785 ath9k_hw_resettxqueue(struct ath_hal *ah, uint32_t q)
786 {
787 	struct ath_hal_5416 *ahp = AH5416(ah);
788 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
789 	struct ath9k_channel *chan = ah->ah_curchan;
790 	struct ath9k_tx_queue_info *qi;
791 	uint32_t cwMin, chanCwMin, value;
792 
793 	if (q >= pCap->total_queues) {
794 		ARN_DBG((ARN_DBG_QUEUE, "%s: invalid queue num %u\n",
795 		    __func__, q));
796 
797 		return (B_FALSE);
798 	}
799 
800 	qi = &ahp->ah_txq[q];
801 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
802 		ARN_DBG((ARN_DBG_QUEUE, "%s: inactive queue %u\n",
803 		    __func__, q));
804 
805 		return (B_TRUE);
806 	}
807 
808 	ARN_DBG((ARN_DBG_QUEUE,
809 	    "%s: reset queue %u\n", __func__, q));
810 
811 	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
812 		if (chan && IS_CHAN_B(chan))
813 			chanCwMin = INIT_CWMIN_11B;
814 		else
815 			chanCwMin = INIT_CWMIN;
816 
817 		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1) {
818 			/* Nothing to do */
819 		}
820 	} else
821 		cwMin = qi->tqi_cwmin;
822 
823 	REG_WRITE(ah, AR_DLCL_IFS(q),
824 	    SM(cwMin, AR_D_LCL_IFS_CWMIN) |
825 	    SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
826 	    SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
827 
828 	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
829 	    SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
830 	    SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
831 	    SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
832 
833 	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
834 	REG_WRITE(ah, AR_DMISC(q),
835 	    AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
836 
837 	if (qi->tqi_cbrPeriod) {
838 		REG_WRITE(ah, AR_QCBRCFG(q),
839 		    SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
840 		    SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
841 		REG_WRITE(ah, AR_QMISC(q),
842 		    REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
843 		    (qi->tqi_cbrOverflowLimit ?
844 		    AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
845 	}
846 	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
847 		REG_WRITE(ah, AR_QRDYTIMECFG(q),
848 		    SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
849 		    AR_Q_RDYTIMECFG_EN);
850 	}
851 
852 	REG_WRITE(ah, AR_DCHNTIME(q),
853 	    SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
854 	    (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
855 
856 	if (qi->tqi_burstTime &&
857 	    (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
858 		REG_WRITE(ah, AR_QMISC(q),
859 		    REG_READ(ah, AR_QMISC(q)) |
860 		    AR_Q_MISC_RDYTIME_EXP_POLICY);
861 
862 	}
863 
864 	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
865 		REG_WRITE(ah, AR_DMISC(q),
866 		    REG_READ(ah, AR_DMISC(q)) |
867 		    AR_D_MISC_POST_FR_BKOFF_DIS);
868 	}
869 	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
870 		REG_WRITE(ah, AR_DMISC(q),
871 		    REG_READ(ah, AR_DMISC(q)) |
872 		    AR_D_MISC_FRAG_BKOFF_EN);
873 	}
874 	switch (qi->tqi_type) {
875 	case ATH9K_TX_QUEUE_BEACON:
876 		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
877 		    AR_Q_MISC_FSP_DBA_GATED |
878 		    AR_Q_MISC_BEACON_USE |
879 		    AR_Q_MISC_CBR_INCR_DIS1);
880 
881 		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
882 		    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
883 		    AR_D_MISC_ARB_LOCKOUT_CNTRL_S) |
884 		    AR_D_MISC_BEACON_USE |
885 		    AR_D_MISC_POST_FR_BKOFF_DIS);
886 		break;
887 	case ATH9K_TX_QUEUE_CAB:
888 		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) |
889 		    AR_Q_MISC_FSP_DBA_GATED |
890 		    AR_Q_MISC_CBR_INCR_DIS1 |
891 		    AR_Q_MISC_CBR_INCR_DIS0);
892 		value = (qi->tqi_readyTime -
893 		    (ah->ah_config.sw_beacon_response_time -
894 		    ah->ah_config.dma_beacon_response_time) -
895 		    ah->ah_config.additional_swba_backoff) * 1024;
896 		REG_WRITE(ah, AR_QRDYTIMECFG(q),
897 		    value | AR_Q_RDYTIMECFG_EN);
898 		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
899 		    (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
900 		    AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
901 		break;
902 	case ATH9K_TX_QUEUE_PSPOLL:
903 		REG_WRITE(ah, AR_QMISC(q),
904 		    REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
905 		break;
906 	case ATH9K_TX_QUEUE_UAPSD:
907 		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
908 		    AR_D_MISC_POST_FR_BKOFF_DIS);
909 		break;
910 	default:
911 		break;
912 	}
913 
914 	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
915 		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
916 		    SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
917 		    AR_D_MISC_ARB_LOCKOUT_CNTRL) |
918 		    AR_D_MISC_POST_FR_BKOFF_DIS);
919 	}
920 
921 	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
922 		ahp->ah_txOkInterruptMask |= 1 << q;
923 	else
924 		ahp->ah_txOkInterruptMask &= ~(1 << q);
925 	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
926 		ahp->ah_txErrInterruptMask |= 1 << q;
927 	else
928 		ahp->ah_txErrInterruptMask &= ~(1 << q);
929 	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
930 		ahp->ah_txDescInterruptMask |= 1 << q;
931 	else
932 		ahp->ah_txDescInterruptMask &= ~(1 << q);
933 	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
934 		ahp->ah_txEolInterruptMask |= 1 << q;
935 	else
936 		ahp->ah_txEolInterruptMask &= ~(1 << q);
937 	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
938 		ahp->ah_txUrnInterruptMask |= 1 << q;
939 	else
940 		ahp->ah_txUrnInterruptMask &= ~(1 << q);
941 	ath9k_hw_set_txq_interrupts(ah, qi);
942 
943 	return (B_TRUE);
944 }
945 
946 /* ARGSUSED */
947 int
948 ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
949     uint32_t pa,
950     struct ath_desc *nds,
951     uint64_t tsf)
952 {
953 	struct ar5416_desc ads;
954 	struct ar5416_desc *adsp = AR5416DESC(ds);
955 	uint32_t phyerr;
956 
957 	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
958 		return (EINPROGRESS);
959 
960 	ads.u.rx = adsp->u.rx;
961 
962 	ds->ds_rxstat.rs_status = 0;
963 	ds->ds_rxstat.rs_flags = 0;
964 
965 	ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
966 	ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
967 
968 	ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
969 	ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
970 	ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
971 	ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
972 	ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
973 	ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
974 	ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
975 	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
976 		ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
977 	else
978 		ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
979 
980 	ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
981 	ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
982 
983 	ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
984 	ds->ds_rxstat.rs_moreaggr =
985 	    (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
986 	ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
987 	ds->ds_rxstat.rs_flags =
988 	    (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
989 	ds->ds_rxstat.rs_flags |=
990 	    (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
991 
992 	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
993 		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
994 	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
995 		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
996 	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
997 		ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
998 
999 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
1000 		if (ads.ds_rxstatus8 & AR_CRCErr)
1001 			ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
1002 		else if (ads.ds_rxstatus8 & AR_PHYErr) {
1003 			ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
1004 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
1005 			ds->ds_rxstat.rs_phyerr = (uint8_t)phyerr; /* LINT */
1006 		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
1007 			ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
1008 		else if (ads.ds_rxstatus8 & AR_MichaelErr)
1009 			ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
1010 	}
1011 
1012 	return (0);
1013 }
1014 
1015 boolean_t
1016 ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
1017     uint32_t size, uint32_t flags)
1018 {
1019 	struct ar5416_desc *ads = AR5416DESC(ds);
1020 	struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
1021 
1022 	ads->ds_ctl1 = size & AR_BufLen;
1023 	if (flags & ATH9K_RXDESC_INTREQ)
1024 		ads->ds_ctl1 |= AR_RxIntrReq;
1025 
1026 	ads->ds_rxstatus8 &= ~AR_RxDone;
1027 	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
1028 		(void) memset(&(ads->u), 0, sizeof (ads->u));
1029 
1030 	return (B_TRUE);
1031 }
1032 
1033 boolean_t
1034 ath9k_hw_setrxabort(struct ath_hal *ah, boolean_t set)
1035 {
1036 	uint32_t reg;
1037 
1038 	if (set) {
1039 		REG_SET_BIT(ah, AR_DIAG_SW,
1040 		    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1041 
1042 		if (!ath9k_hw_wait(ah, AR_OBS_BUS_1,
1043 		    AR_OBS_BUS_1_RX_STATE, 0)) {
1044 			REG_CLR_BIT(ah, AR_DIAG_SW,
1045 			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1046 
1047 			reg = REG_READ(ah, AR_OBS_BUS_1);
1048 
1049 			ARN_DBG((ARN_DBG_FATAL,
1050 			    "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
1051 			    __func__, reg));
1052 
1053 			return (B_FALSE);
1054 		}
1055 	} else {
1056 		REG_CLR_BIT(ah, AR_DIAG_SW,
1057 		    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1058 	}
1059 
1060 	return (B_TRUE);
1061 }
1062 
1063 void
1064 ath9k_hw_putrxbuf(struct ath_hal *ah, uint32_t rxdp)
1065 {
1066 	REG_WRITE(ah, AR_RXDP, rxdp);
1067 }
1068 
1069 void
1070 ath9k_hw_rxena(struct ath_hal *ah)
1071 {
1072 	REG_WRITE(ah, AR_CR, AR_CR_RXE);
1073 }
1074 
1075 void
1076 ath9k_hw_startpcureceive(struct ath_hal *ah)
1077 {
1078 	ath9k_enable_mib_counters(ah);
1079 
1080 	ath9k_ani_reset(ah);
1081 
1082 	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
1083 }
1084 
1085 void
1086 ath9k_hw_stoppcurecv(struct ath_hal *ah)
1087 {
1088 	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
1089 
1090 	ath9k_hw_disable_mib_counters(ah);
1091 }
1092 
1093 boolean_t
1094 ath9k_hw_stopdmarecv(struct ath_hal *ah)
1095 {
1096 	REG_WRITE(ah, AR_CR, AR_CR_RXD);
1097 
1098 	if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
1099 		ARN_DBG((ARN_DBG_QUEUE, "arn: ath9k_hw_stopdmarecv(): "
1100 		    "dma failed to stop in 10ms\n"
1101 		    "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
1102 		    REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)));
1103 		return (B_FALSE);
1104 	} else {
1105 		return (B_TRUE);
1106 	}
1107 }
1108