1b7d5e03cSMatthew Dillon /*
2b7d5e03cSMatthew Dillon  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3b7d5e03cSMatthew Dillon  *
4b7d5e03cSMatthew Dillon  * Permission to use, copy, modify, and/or distribute this software for any
5b7d5e03cSMatthew Dillon  * purpose with or without fee is hereby granted, provided that the above
6b7d5e03cSMatthew Dillon  * copyright notice and this permission notice appear in all copies.
7b7d5e03cSMatthew Dillon  *
8b7d5e03cSMatthew Dillon  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9b7d5e03cSMatthew Dillon  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10b7d5e03cSMatthew Dillon  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11b7d5e03cSMatthew Dillon  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12b7d5e03cSMatthew Dillon  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13b7d5e03cSMatthew Dillon  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14b7d5e03cSMatthew Dillon  * PERFORMANCE OF THIS SOFTWARE.
15b7d5e03cSMatthew Dillon  */
16b7d5e03cSMatthew Dillon 
17b7d5e03cSMatthew Dillon #include "opt_ah.h"
18b7d5e03cSMatthew Dillon 
19b7d5e03cSMatthew Dillon #include "ah.h"
20b7d5e03cSMatthew Dillon #include "ah_desc.h"
21b7d5e03cSMatthew Dillon #include "ah_internal.h"
22b7d5e03cSMatthew Dillon 
23b7d5e03cSMatthew Dillon #include "ar9300/ar9300desc.h"
24b7d5e03cSMatthew Dillon #include "ar9300/ar9300.h"
25b7d5e03cSMatthew Dillon #include "ar9300/ar9300reg.h"
26b7d5e03cSMatthew Dillon #include "ar9300/ar9300phy.h"
27b7d5e03cSMatthew Dillon #include "ah_devid.h"
28b7d5e03cSMatthew Dillon 
29b7d5e03cSMatthew Dillon #if AH_BYTE_ORDER == AH_BIG_ENDIAN
30b7d5e03cSMatthew Dillon static void ar9300_swap_tx_desc(void *ds);
31b7d5e03cSMatthew Dillon #endif
32b7d5e03cSMatthew Dillon 
33b7d5e03cSMatthew Dillon void
ar9300_tx_req_intr_desc(struct ath_hal * ah,void * ds)34b7d5e03cSMatthew Dillon ar9300_tx_req_intr_desc(struct ath_hal *ah, void *ds)
35b7d5e03cSMatthew Dillon {
36b7d5e03cSMatthew Dillon     HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
37b7d5e03cSMatthew Dillon         "%s:Desc Interrupt not supported\n", __func__);
38b7d5e03cSMatthew Dillon }
39b7d5e03cSMatthew Dillon 
40b7d5e03cSMatthew Dillon static inline u_int16_t
ar9300_calc_ptr_chk_sum(struct ar9300_txc * ads)41b7d5e03cSMatthew Dillon ar9300_calc_ptr_chk_sum(struct ar9300_txc *ads)
42b7d5e03cSMatthew Dillon {
43b7d5e03cSMatthew Dillon     u_int checksum;
44b7d5e03cSMatthew Dillon     u_int16_t ptrchecksum;
45b7d5e03cSMatthew Dillon 
46b7d5e03cSMatthew Dillon     /* checksum = __bswap32(ads->ds_info) + ads->ds_link */
47b7d5e03cSMatthew Dillon     checksum =    ads->ds_info + ads->ds_link
48b7d5e03cSMatthew Dillon                 + ads->ds_data0 + ads->ds_ctl3
49b7d5e03cSMatthew Dillon                 + ads->ds_data1 + ads->ds_ctl5
50b7d5e03cSMatthew Dillon                 + ads->ds_data2 + ads->ds_ctl7
51b7d5e03cSMatthew Dillon                 + ads->ds_data3 + ads->ds_ctl9;
52b7d5e03cSMatthew Dillon 
53b7d5e03cSMatthew Dillon     ptrchecksum = ((checksum & 0xffff) + (checksum >> 16)) & AR_tx_ptr_chk_sum;
54b7d5e03cSMatthew Dillon     return ptrchecksum;
55b7d5e03cSMatthew Dillon }
56b7d5e03cSMatthew Dillon 
57b7d5e03cSMatthew Dillon HAL_BOOL
ar9300_fill_tx_desc(struct ath_hal * ah,void * ds,HAL_DMA_ADDR * buf_addr,u_int32_t * seg_len,u_int desc_id,u_int qcu,HAL_KEY_TYPE key_type,HAL_BOOL first_seg,HAL_BOOL last_seg,const void * ds0)58b7d5e03cSMatthew Dillon ar9300_fill_tx_desc(
59b7d5e03cSMatthew Dillon     struct ath_hal *ah,
60b7d5e03cSMatthew Dillon     void *ds,
61b7d5e03cSMatthew Dillon     HAL_DMA_ADDR *buf_addr,
62b7d5e03cSMatthew Dillon     u_int32_t *seg_len,
63b7d5e03cSMatthew Dillon     u_int desc_id,
64b7d5e03cSMatthew Dillon     u_int qcu,
65b7d5e03cSMatthew Dillon     HAL_KEY_TYPE key_type,
66b7d5e03cSMatthew Dillon     HAL_BOOL first_seg,
67b7d5e03cSMatthew Dillon     HAL_BOOL last_seg,
68b7d5e03cSMatthew Dillon     const void *ds0)
69b7d5e03cSMatthew Dillon {
70b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
71*848b370cSMatthew Dillon     short desclen;
72b7d5e03cSMatthew Dillon 
73b7d5e03cSMatthew Dillon     /* Fill TXC info field */
74*848b370cSMatthew Dillon     desclen = (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) ? 0x18 : 0x17;
75*848b370cSMatthew Dillon     ads->ds_info = TXC_INFO(qcu, desclen);
76b7d5e03cSMatthew Dillon 
77b7d5e03cSMatthew Dillon     /* Set the buffer addresses */
78b7d5e03cSMatthew Dillon     ads->ds_data0 = buf_addr[0];
79b7d5e03cSMatthew Dillon     ads->ds_data1 = buf_addr[1];
80b7d5e03cSMatthew Dillon     ads->ds_data2 = buf_addr[2];
81b7d5e03cSMatthew Dillon     ads->ds_data3 = buf_addr[3];
82b7d5e03cSMatthew Dillon 
83b7d5e03cSMatthew Dillon     /* Set the buffer lengths */
84b7d5e03cSMatthew Dillon     ads->ds_ctl3 = (seg_len[0] << AR_buf_len_S) & AR_buf_len;
85b7d5e03cSMatthew Dillon     ads->ds_ctl5 = (seg_len[1] << AR_buf_len_S) & AR_buf_len;
86b7d5e03cSMatthew Dillon     ads->ds_ctl7 = (seg_len[2] << AR_buf_len_S) & AR_buf_len;
87b7d5e03cSMatthew Dillon     ads->ds_ctl9 = (seg_len[3] << AR_buf_len_S) & AR_buf_len;
88b7d5e03cSMatthew Dillon 
89b7d5e03cSMatthew Dillon     /* Fill in pointer checksum and descriptor id */
90b7d5e03cSMatthew Dillon     ads->ds_ctl10 = (desc_id << AR_tx_desc_id_S) | ar9300_calc_ptr_chk_sum(ads);
91b7d5e03cSMatthew Dillon 
92b7d5e03cSMatthew Dillon     if (first_seg) {
93b7d5e03cSMatthew Dillon         /*
94b7d5e03cSMatthew Dillon          * First descriptor, don't clobber xmit control data
95b7d5e03cSMatthew Dillon          * setup by ar9300_set_11n_tx_desc.
96b7d5e03cSMatthew Dillon          *
97b7d5e03cSMatthew Dillon          * Note: AR_encr_type is already setup in the first descriptor by
98b7d5e03cSMatthew Dillon          *       set_11n_tx_desc().
99b7d5e03cSMatthew Dillon          */
100b7d5e03cSMatthew Dillon         ads->ds_ctl12 |= (last_seg ? 0 : AR_tx_more);
101b7d5e03cSMatthew Dillon     } else if (last_seg) { /* !first_seg && last_seg */
102b7d5e03cSMatthew Dillon         /*
103b7d5e03cSMatthew Dillon          * Last descriptor in a multi-descriptor frame,
104b7d5e03cSMatthew Dillon          * copy the multi-rate transmit parameters from
105b7d5e03cSMatthew Dillon          * the first frame for processing on completion.
106b7d5e03cSMatthew Dillon          */
107b7d5e03cSMatthew Dillon         ads->ds_ctl11 = 0;
108b7d5e03cSMatthew Dillon         ads->ds_ctl12 = 0;
109b7d5e03cSMatthew Dillon #ifdef AH_NEED_DESC_SWAP
110b7d5e03cSMatthew Dillon         ads->ds_ctl13 = __bswap32(AR9300TXC_CONST(ds0)->ds_ctl13);
111b7d5e03cSMatthew Dillon         ads->ds_ctl14 = __bswap32(AR9300TXC_CONST(ds0)->ds_ctl14);
112b7d5e03cSMatthew Dillon         ads->ds_ctl17 = __bswap32(SM(key_type, AR_encr_type));
113b7d5e03cSMatthew Dillon #else
114b7d5e03cSMatthew Dillon         ads->ds_ctl13 = AR9300TXC_CONST(ds0)->ds_ctl13;
115b7d5e03cSMatthew Dillon         ads->ds_ctl14 = AR9300TXC_CONST(ds0)->ds_ctl14;
116b7d5e03cSMatthew Dillon         ads->ds_ctl17 = SM(key_type, AR_encr_type);
117b7d5e03cSMatthew Dillon #endif
118b7d5e03cSMatthew Dillon     } else { /* !first_seg && !last_seg */
119b7d5e03cSMatthew Dillon         /*
120b7d5e03cSMatthew Dillon          * XXX Intermediate descriptor in a multi-descriptor frame.
121b7d5e03cSMatthew Dillon          */
122b7d5e03cSMatthew Dillon         ads->ds_ctl11 = 0;
123b7d5e03cSMatthew Dillon         ads->ds_ctl12 = AR_tx_more;
124b7d5e03cSMatthew Dillon         ads->ds_ctl13 = 0;
125b7d5e03cSMatthew Dillon         ads->ds_ctl14 = 0;
126b7d5e03cSMatthew Dillon         ads->ds_ctl17 = SM(key_type, AR_encr_type);
127b7d5e03cSMatthew Dillon     }
128b7d5e03cSMatthew Dillon 
129*848b370cSMatthew Dillon     /* Only relevant for Jupiter/Aphrodite */
130*848b370cSMatthew Dillon     ads->ds_ctl23 = 0;
131*848b370cSMatthew Dillon 
132b7d5e03cSMatthew Dillon     return AH_TRUE;
133b7d5e03cSMatthew Dillon }
134b7d5e03cSMatthew Dillon 
135b7d5e03cSMatthew Dillon void
ar9300_set_desc_link(struct ath_hal * ah,void * ds,u_int32_t link)136b7d5e03cSMatthew Dillon ar9300_set_desc_link(struct ath_hal *ah, void *ds, u_int32_t link)
137b7d5e03cSMatthew Dillon {
138b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
139b7d5e03cSMatthew Dillon 
140b7d5e03cSMatthew Dillon     ads->ds_link = link;
141b7d5e03cSMatthew Dillon 
142b7d5e03cSMatthew Dillon     /* TODO - checksum is calculated twice for subframes
143b7d5e03cSMatthew Dillon      * Once in filldesc and again when linked. Need to fix.
144b7d5e03cSMatthew Dillon      */
145b7d5e03cSMatthew Dillon     /* Fill in pointer checksum.  Preserve descriptor id */
146b7d5e03cSMatthew Dillon     ads->ds_ctl10 &= ~AR_tx_ptr_chk_sum;
147b7d5e03cSMatthew Dillon     ads->ds_ctl10 |= ar9300_calc_ptr_chk_sum(ads);
148b7d5e03cSMatthew Dillon }
149b7d5e03cSMatthew Dillon 
150b7d5e03cSMatthew Dillon void
ar9300_get_desc_link_ptr(struct ath_hal * ah,void * ds,u_int32_t ** link)151b7d5e03cSMatthew Dillon ar9300_get_desc_link_ptr(struct ath_hal *ah, void *ds, u_int32_t **link)
152b7d5e03cSMatthew Dillon {
153b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
154b7d5e03cSMatthew Dillon 
155b7d5e03cSMatthew Dillon     *link = &ads->ds_link;
156b7d5e03cSMatthew Dillon }
157b7d5e03cSMatthew Dillon 
158b7d5e03cSMatthew Dillon void
ar9300_clear_tx_desc_status(struct ath_hal * ah,void * ds)159b7d5e03cSMatthew Dillon ar9300_clear_tx_desc_status(struct ath_hal *ah, void *ds)
160b7d5e03cSMatthew Dillon {
161b7d5e03cSMatthew Dillon     struct ar9300_txs *ads = AR9300TXS(ds);
162b7d5e03cSMatthew Dillon     ads->status1 = ads->status2 = 0;
163b7d5e03cSMatthew Dillon     ads->status3 = ads->status4 = 0;
164b7d5e03cSMatthew Dillon     ads->status5 = ads->status6 = 0;
165b7d5e03cSMatthew Dillon     ads->status7 = ads->status8 = 0;
166b7d5e03cSMatthew Dillon }
167b7d5e03cSMatthew Dillon 
168b7d5e03cSMatthew Dillon #ifdef ATH_SWRETRY
169b7d5e03cSMatthew Dillon void
ar9300_clear_dest_mask(struct ath_hal * ah,void * ds)170b7d5e03cSMatthew Dillon ar9300_clear_dest_mask(struct ath_hal *ah, void *ds)
171b7d5e03cSMatthew Dillon {
172b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
173b7d5e03cSMatthew Dillon     ads->ds_ctl11 |= AR_clr_dest_mask;
174b7d5e03cSMatthew Dillon }
175b7d5e03cSMatthew Dillon #endif
176b7d5e03cSMatthew Dillon 
177b7d5e03cSMatthew Dillon #if AH_BYTE_ORDER == AH_BIG_ENDIAN
178b7d5e03cSMatthew Dillon /* XXX what words need swapping */
179b7d5e03cSMatthew Dillon /* Swap transmit descriptor */
180b7d5e03cSMatthew Dillon static __inline void
ar9300_swap_tx_desc(void * dsp)181b7d5e03cSMatthew Dillon ar9300_swap_tx_desc(void *dsp)
182b7d5e03cSMatthew Dillon {
183b7d5e03cSMatthew Dillon     struct ar9300_txs *ds = (struct ar9300_txs *)dsp;
184b7d5e03cSMatthew Dillon 
185b7d5e03cSMatthew Dillon     ds->ds_info = __bswap32(ds->ds_info);
186b7d5e03cSMatthew Dillon     ds->status1 = __bswap32(ds->status1);
187b7d5e03cSMatthew Dillon     ds->status2 = __bswap32(ds->status2);
188b7d5e03cSMatthew Dillon     ds->status3 = __bswap32(ds->status3);
189b7d5e03cSMatthew Dillon     ds->status4 = __bswap32(ds->status4);
190b7d5e03cSMatthew Dillon     ds->status5 = __bswap32(ds->status5);
191b7d5e03cSMatthew Dillon     ds->status6 = __bswap32(ds->status6);
192b7d5e03cSMatthew Dillon     ds->status7 = __bswap32(ds->status7);
193b7d5e03cSMatthew Dillon     ds->status8 = __bswap32(ds->status8);
194b7d5e03cSMatthew Dillon }
195b7d5e03cSMatthew Dillon #endif
196b7d5e03cSMatthew Dillon 
197b7d5e03cSMatthew Dillon 
198b7d5e03cSMatthew Dillon /*
199b7d5e03cSMatthew Dillon  * Extract the transmit rate code.
200b7d5e03cSMatthew Dillon  */
201b7d5e03cSMatthew Dillon void
ar9300_get_tx_rate_code(struct ath_hal * ah,void * ds,struct ath_tx_status * ts)202b7d5e03cSMatthew Dillon ar9300_get_tx_rate_code(struct ath_hal *ah, void *ds, struct ath_tx_status *ts)
203b7d5e03cSMatthew Dillon {
204b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
205b7d5e03cSMatthew Dillon 
206b7d5e03cSMatthew Dillon     switch (ts->ts_finaltsi) {
207b7d5e03cSMatthew Dillon     case 0:
208b7d5e03cSMatthew Dillon         ts->ts_rate = MS(ads->ds_ctl14, AR_xmit_rate0);
209b7d5e03cSMatthew Dillon         break;
210b7d5e03cSMatthew Dillon     case 1:
211b7d5e03cSMatthew Dillon         ts->ts_rate = MS(ads->ds_ctl14, AR_xmit_rate1);
212b7d5e03cSMatthew Dillon         break;
213b7d5e03cSMatthew Dillon     case 2:
214b7d5e03cSMatthew Dillon         ts->ts_rate = MS(ads->ds_ctl14, AR_xmit_rate2);
215b7d5e03cSMatthew Dillon         break;
216b7d5e03cSMatthew Dillon     case 3:
217b7d5e03cSMatthew Dillon         ts->ts_rate = MS(ads->ds_ctl14, AR_xmit_rate3);
218b7d5e03cSMatthew Dillon         break;
219b7d5e03cSMatthew Dillon     }
220b7d5e03cSMatthew Dillon 
221b7d5e03cSMatthew Dillon     ar9300_set_selfgenrate_limit(ah, ts->ts_rate);
222b7d5e03cSMatthew Dillon }
223b7d5e03cSMatthew Dillon 
224b7d5e03cSMatthew Dillon /*
225b7d5e03cSMatthew Dillon  * Get TX Status descriptor contents.
226b7d5e03cSMatthew Dillon  */
227b7d5e03cSMatthew Dillon void
ar9300_get_raw_tx_desc(struct ath_hal * ah,u_int32_t * txstatus)228b7d5e03cSMatthew Dillon ar9300_get_raw_tx_desc(struct ath_hal *ah, u_int32_t *txstatus)
229b7d5e03cSMatthew Dillon {
230b7d5e03cSMatthew Dillon     struct ath_hal_9300 *ahp = AH9300(ah);
231b7d5e03cSMatthew Dillon     struct ar9300_txs *ads;
232b7d5e03cSMatthew Dillon 
233b7d5e03cSMatthew Dillon     ads = &ahp->ts_ring[ahp->ts_tail];
234b7d5e03cSMatthew Dillon 
235b7d5e03cSMatthew Dillon     OS_MEMCPY(txstatus, ads, sizeof(struct ar9300_txs));
236b7d5e03cSMatthew Dillon }
237b7d5e03cSMatthew Dillon 
238b7d5e03cSMatthew Dillon /*
239b7d5e03cSMatthew Dillon  * Processing of HW TX descriptor.
240b7d5e03cSMatthew Dillon  */
241b7d5e03cSMatthew Dillon HAL_STATUS
ar9300_proc_tx_desc(struct ath_hal * ah,void * txstatus)242b7d5e03cSMatthew Dillon ar9300_proc_tx_desc(struct ath_hal *ah, void *txstatus)
243b7d5e03cSMatthew Dillon {
244b7d5e03cSMatthew Dillon     struct ath_hal_9300 *ahp = AH9300(ah);
245b7d5e03cSMatthew Dillon     struct ar9300_txs *ads;
246b7d5e03cSMatthew Dillon     struct ath_tx_status *ts = (struct ath_tx_status *)txstatus;
247b7d5e03cSMatthew Dillon     u_int32_t dsinfo;
248b7d5e03cSMatthew Dillon 
249b7d5e03cSMatthew Dillon     ads = &ahp->ts_ring[ahp->ts_tail];
250b7d5e03cSMatthew Dillon 
251b7d5e03cSMatthew Dillon     if ((ads->status8 & AR_tx_done) == 0) {
252b7d5e03cSMatthew Dillon         return HAL_EINPROGRESS;
253b7d5e03cSMatthew Dillon     }
254b7d5e03cSMatthew Dillon 
255b7d5e03cSMatthew Dillon     /*
256b7d5e03cSMatthew Dillon      * Sanity check
257b7d5e03cSMatthew Dillon      */
258b7d5e03cSMatthew Dillon 
259b7d5e03cSMatthew Dillon #if 0
260b7d5e03cSMatthew Dillon     ath_hal_printf(ah,
261b7d5e03cSMatthew Dillon         "CHH: tail=%d\n", ahp->ts_tail);
262b7d5e03cSMatthew Dillon     ath_hal_printf(ah,
263b7d5e03cSMatthew Dillon         "CHH: ds_info 0x%x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
264b7d5e03cSMatthew Dillon         ads->ds_info,
265b7d5e03cSMatthew Dillon         ads->status1,
266b7d5e03cSMatthew Dillon         ads->status2,
267b7d5e03cSMatthew Dillon         ads->status3,
268b7d5e03cSMatthew Dillon         ads->status4,
269b7d5e03cSMatthew Dillon         ads->status5,
270b7d5e03cSMatthew Dillon         ads->status6,
271b7d5e03cSMatthew Dillon         ads->status7,
272b7d5e03cSMatthew Dillon         ads->status8);
273b7d5e03cSMatthew Dillon #endif
274b7d5e03cSMatthew Dillon 
275b7d5e03cSMatthew Dillon 
276b7d5e03cSMatthew Dillon     /* Increment the tail to point to the next status element. */
277b7d5e03cSMatthew Dillon     ahp->ts_tail = (ahp->ts_tail + 1) & (ahp->ts_size-1);
278b7d5e03cSMatthew Dillon 
279b7d5e03cSMatthew Dillon     /*
280b7d5e03cSMatthew Dillon     ** For big endian systems, ds_info is not swapped as the other
281b7d5e03cSMatthew Dillon     ** registers are.  Ensure we use the bswap32 version (which is
282b7d5e03cSMatthew Dillon     ** defined to "nothing" in little endian systems
283b7d5e03cSMatthew Dillon     */
284b7d5e03cSMatthew Dillon 
285b7d5e03cSMatthew Dillon     dsinfo = ads->ds_info;
286b7d5e03cSMatthew Dillon 
287b7d5e03cSMatthew Dillon     if ((MS(dsinfo, AR_desc_id) != ATHEROS_VENDOR_ID) ||
288b7d5e03cSMatthew Dillon         (MS(dsinfo, AR_tx_rx_desc) != 1))
289b7d5e03cSMatthew Dillon     {
290b7d5e03cSMatthew Dillon         HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Tx Descriptor error %x\n",
291b7d5e03cSMatthew Dillon                  __func__, dsinfo);
292b7d5e03cSMatthew Dillon         HALASSERT(0);
293b7d5e03cSMatthew Dillon         /* Zero out the status for reuse */
294b7d5e03cSMatthew Dillon         OS_MEMZERO(ads, sizeof(struct ar9300_txs));
295b7d5e03cSMatthew Dillon         return HAL_EIO;
296b7d5e03cSMatthew Dillon     }
297b7d5e03cSMatthew Dillon 
298b7d5e03cSMatthew Dillon     /* Update software copies of the HW status */
299b7d5e03cSMatthew Dillon     ts->ts_queue_id = MS(dsinfo, AR_tx_qcu_num);
300b7d5e03cSMatthew Dillon     ts->ts_desc_id = MS(ads->status1, AR_tx_desc_id);
301b7d5e03cSMatthew Dillon     ts->ts_seqnum = MS(ads->status8, AR_seq_num);
302b7d5e03cSMatthew Dillon     ts->ts_tstamp = ads->status4;
303b7d5e03cSMatthew Dillon     ts->ts_status = 0;
304b7d5e03cSMatthew Dillon     ts->ts_flags  = 0;
305b7d5e03cSMatthew Dillon 
306b7d5e03cSMatthew Dillon     if (ads->status3 & AR_excessive_retries) {
307b7d5e03cSMatthew Dillon         ts->ts_status |= HAL_TXERR_XRETRY;
308b7d5e03cSMatthew Dillon     }
309b7d5e03cSMatthew Dillon     if (ads->status3 & AR_filtered) {
310b7d5e03cSMatthew Dillon         ts->ts_status |= HAL_TXERR_FILT;
311b7d5e03cSMatthew Dillon     }
312b7d5e03cSMatthew Dillon     if (ads->status3 & AR_fifounderrun) {
313b7d5e03cSMatthew Dillon         ts->ts_status |= HAL_TXERR_FIFO;
314b7d5e03cSMatthew Dillon         ar9300_update_tx_trig_level(ah, AH_TRUE);
315b7d5e03cSMatthew Dillon     }
316b7d5e03cSMatthew Dillon     if (ads->status8 & AR_tx_op_exceeded) {
317b7d5e03cSMatthew Dillon         ts->ts_status |= HAL_TXERR_XTXOP;
318b7d5e03cSMatthew Dillon     }
319b7d5e03cSMatthew Dillon     if (ads->status3 & AR_tx_timer_expired) {
320b7d5e03cSMatthew Dillon         ts->ts_status |= HAL_TXERR_TIMER_EXPIRED;
321b7d5e03cSMatthew Dillon     }
322b7d5e03cSMatthew Dillon     if (ads->status3 & AR_desc_cfg_err) {
323b7d5e03cSMatthew Dillon         ts->ts_flags |= HAL_TX_DESC_CFG_ERR;
324b7d5e03cSMatthew Dillon     }
325b7d5e03cSMatthew Dillon     if (ads->status3 & AR_tx_data_underrun) {
326b7d5e03cSMatthew Dillon         ts->ts_flags |= HAL_TX_DATA_UNDERRUN;
327b7d5e03cSMatthew Dillon         ar9300_update_tx_trig_level(ah, AH_TRUE);
328b7d5e03cSMatthew Dillon     }
329b7d5e03cSMatthew Dillon     if (ads->status3 & AR_tx_delim_underrun) {
330b7d5e03cSMatthew Dillon         ts->ts_flags |= HAL_TX_DELIM_UNDERRUN;
331b7d5e03cSMatthew Dillon         ar9300_update_tx_trig_level(ah, AH_TRUE);
332b7d5e03cSMatthew Dillon     }
333b7d5e03cSMatthew Dillon     if (ads->status2 & AR_tx_ba_status) {
334b7d5e03cSMatthew Dillon         ts->ts_flags |= HAL_TX_BA;
335b7d5e03cSMatthew Dillon         ts->ts_ba_low = ads->status5;
336b7d5e03cSMatthew Dillon         ts->ts_ba_high = ads->status6;
337b7d5e03cSMatthew Dillon     }
338b7d5e03cSMatthew Dillon 
339b7d5e03cSMatthew Dillon     /*
340b7d5e03cSMatthew Dillon      * Extract the transmit rate.
341b7d5e03cSMatthew Dillon      */
342b7d5e03cSMatthew Dillon     ts->ts_finaltsi = MS(ads->status8, AR_final_tx_idx);
343b7d5e03cSMatthew Dillon 
344b7d5e03cSMatthew Dillon     ts->ts_rssi = MS(ads->status7, AR_tx_rssi_combined);
345b7d5e03cSMatthew Dillon     ts->ts_rssi_ctl[0] = MS(ads->status2, AR_tx_rssi_ant00);
346b7d5e03cSMatthew Dillon     ts->ts_rssi_ctl[1] = MS(ads->status2, AR_tx_rssi_ant01);
347b7d5e03cSMatthew Dillon     ts->ts_rssi_ctl[2] = MS(ads->status2, AR_tx_rssi_ant02);
348b7d5e03cSMatthew Dillon     ts->ts_rssi_ext[0] = MS(ads->status7, AR_tx_rssi_ant10);
349b7d5e03cSMatthew Dillon     ts->ts_rssi_ext[1] = MS(ads->status7, AR_tx_rssi_ant11);
350b7d5e03cSMatthew Dillon     ts->ts_rssi_ext[2] = MS(ads->status7, AR_tx_rssi_ant12);
351b7d5e03cSMatthew Dillon     ts->ts_shortretry = MS(ads->status3, AR_rts_fail_cnt);
352b7d5e03cSMatthew Dillon     ts->ts_longretry = MS(ads->status3, AR_data_fail_cnt);
353b7d5e03cSMatthew Dillon     ts->ts_virtcol = MS(ads->status3, AR_virt_retry_cnt);
354b7d5e03cSMatthew Dillon     ts->ts_antenna = 0;
355b7d5e03cSMatthew Dillon 
356b7d5e03cSMatthew Dillon     /* extract TID from block ack */
357b7d5e03cSMatthew Dillon     ts->ts_tid = MS(ads->status8, AR_tx_tid);
358b7d5e03cSMatthew Dillon 
359b7d5e03cSMatthew Dillon     /* Zero out the status for reuse */
360b7d5e03cSMatthew Dillon     OS_MEMZERO(ads, sizeof(struct ar9300_txs));
361b7d5e03cSMatthew Dillon 
362b7d5e03cSMatthew Dillon     return HAL_OK;
363b7d5e03cSMatthew Dillon }
364b7d5e03cSMatthew Dillon 
365b7d5e03cSMatthew Dillon /*
366b7d5e03cSMatthew Dillon  * Calculate air time of a transmit packet
367b7d5e03cSMatthew Dillon  * if comp_wastedt is 1, calculate air time only for failed subframes
368b7d5e03cSMatthew Dillon  * this is required for VOW_DCS ( dynamic channel selection )
369b7d5e03cSMatthew Dillon  */
370b7d5e03cSMatthew Dillon u_int32_t
ar9300_calc_tx_airtime(struct ath_hal * ah,void * ds,struct ath_tx_status * ts,HAL_BOOL comp_wastedt,u_int8_t nbad,u_int8_t nframes)371b7d5e03cSMatthew Dillon ar9300_calc_tx_airtime(struct ath_hal *ah, void *ds, struct ath_tx_status *ts,
372b7d5e03cSMatthew Dillon         HAL_BOOL comp_wastedt, u_int8_t nbad, u_int8_t nframes )
373b7d5e03cSMatthew Dillon {
374b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
375b7d5e03cSMatthew Dillon     int finalindex_tries;
376b7d5e03cSMatthew Dillon     u_int32_t airtime, lastrate_dur;
377b7d5e03cSMatthew Dillon 
378b7d5e03cSMatthew Dillon 
379b7d5e03cSMatthew Dillon     /*
380b7d5e03cSMatthew Dillon      * Number of attempts made on the final index
381b7d5e03cSMatthew Dillon      * Note: If no BA was recv, then the data_fail_cnt is the number of tries
382b7d5e03cSMatthew Dillon      * made on the final index.  If BA was recv, then add 1 to account for the
383b7d5e03cSMatthew Dillon      * successful attempt.
384b7d5e03cSMatthew Dillon      */
385b7d5e03cSMatthew Dillon     if ( !comp_wastedt ){
386b7d5e03cSMatthew Dillon         finalindex_tries = ts->ts_longretry + (ts->ts_flags & HAL_TX_BA)? 1 : 0;
387b7d5e03cSMatthew Dillon     } else {
388b7d5e03cSMatthew Dillon         finalindex_tries = ts->ts_longretry ;
389b7d5e03cSMatthew Dillon     }
390b7d5e03cSMatthew Dillon 
391b7d5e03cSMatthew Dillon     /*
392b7d5e03cSMatthew Dillon      * Calculate time of transmit on air for packet including retries
393b7d5e03cSMatthew Dillon      * at different rates.
394b7d5e03cSMatthew Dillon      */
395b7d5e03cSMatthew Dillon     switch (ts->ts_finaltsi) {
396b7d5e03cSMatthew Dillon     case 0:
397b7d5e03cSMatthew Dillon         lastrate_dur = MS(ads->ds_ctl15, AR_packet_dur0);
398b7d5e03cSMatthew Dillon         airtime = (lastrate_dur * finalindex_tries);
399b7d5e03cSMatthew Dillon         break;
400b7d5e03cSMatthew Dillon     case 1:
401b7d5e03cSMatthew Dillon         lastrate_dur = MS(ads->ds_ctl15, AR_packet_dur1);
402b7d5e03cSMatthew Dillon         airtime = (lastrate_dur * finalindex_tries) +
403b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries0) *
404b7d5e03cSMatthew Dillon              MS(ads->ds_ctl15, AR_packet_dur0));
405b7d5e03cSMatthew Dillon         break;
406b7d5e03cSMatthew Dillon     case 2:
407b7d5e03cSMatthew Dillon         lastrate_dur = MS(ads->ds_ctl16, AR_packet_dur2);
408b7d5e03cSMatthew Dillon         airtime = (lastrate_dur * finalindex_tries) +
409b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries1) *
410b7d5e03cSMatthew Dillon              MS(ads->ds_ctl15, AR_packet_dur1)) +
411b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries0) *
412b7d5e03cSMatthew Dillon              MS(ads->ds_ctl15, AR_packet_dur0));
413b7d5e03cSMatthew Dillon         break;
414b7d5e03cSMatthew Dillon     case 3:
415b7d5e03cSMatthew Dillon         lastrate_dur = MS(ads->ds_ctl16, AR_packet_dur3);
416b7d5e03cSMatthew Dillon         airtime = (lastrate_dur * finalindex_tries) +
417b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries2) *
418b7d5e03cSMatthew Dillon              MS(ads->ds_ctl16, AR_packet_dur2)) +
419b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries1) *
420b7d5e03cSMatthew Dillon              MS(ads->ds_ctl15, AR_packet_dur1)) +
421b7d5e03cSMatthew Dillon             (MS(ads->ds_ctl13, AR_xmit_data_tries0) *
422b7d5e03cSMatthew Dillon              MS(ads->ds_ctl15, AR_packet_dur0));
423b7d5e03cSMatthew Dillon         break;
424b7d5e03cSMatthew Dillon     default:
425b7d5e03cSMatthew Dillon         HALASSERT(0);
426b7d5e03cSMatthew Dillon         return 0;
427b7d5e03cSMatthew Dillon     }
428b7d5e03cSMatthew Dillon 
429b7d5e03cSMatthew Dillon     if ( comp_wastedt && (ts->ts_flags & HAL_TX_BA)){
430b7d5e03cSMatthew Dillon         airtime += nbad?((lastrate_dur*nbad) / nframes):0;
431b7d5e03cSMatthew Dillon     }
432b7d5e03cSMatthew Dillon     return airtime;
433b7d5e03cSMatthew Dillon 
434b7d5e03cSMatthew Dillon }
435b7d5e03cSMatthew Dillon 
436b7d5e03cSMatthew Dillon #ifdef AH_PRIVATE_DIAG
437b7d5e03cSMatthew Dillon void
ar9300__cont_tx_mode(struct ath_hal * ah,void * ds,int mode)438b7d5e03cSMatthew Dillon ar9300__cont_tx_mode(struct ath_hal *ah, void *ds, int mode)
439b7d5e03cSMatthew Dillon {
440b7d5e03cSMatthew Dillon #if 0
441b7d5e03cSMatthew Dillon     static int qnum = 0;
442b7d5e03cSMatthew Dillon     int i;
443b7d5e03cSMatthew Dillon     unsigned int qbits, val, val1, val2;
444b7d5e03cSMatthew Dillon     int prefetch;
445b7d5e03cSMatthew Dillon     struct ar9300_txs *ads = AR9300TXS(ds);
446b7d5e03cSMatthew Dillon 
447b7d5e03cSMatthew Dillon     if (mode == 10) {
448b7d5e03cSMatthew Dillon         return;
449b7d5e03cSMatthew Dillon     }
450b7d5e03cSMatthew Dillon 
451b7d5e03cSMatthew Dillon     if (mode == 7) { /* print status from the cont tx desc */
452b7d5e03cSMatthew Dillon         if (ads) {
453b7d5e03cSMatthew Dillon             val1 = ads->ds_txstatus1;
454b7d5e03cSMatthew Dillon             val2 = ads->ds_txstatus2;
455b7d5e03cSMatthew Dillon             HALDEBUG(ah, HAL_DEBUG_TXDESC, "s0(%x) s1(%x)\n",
456b7d5e03cSMatthew Dillon                                        (unsigned)val1, (unsigned)val2);
457b7d5e03cSMatthew Dillon         }
458b7d5e03cSMatthew Dillon         HALDEBUG(ah, HAL_DEBUG_TXDESC, "txe(%x) txd(%x)\n",
459b7d5e03cSMatthew Dillon                                    OS_REG_READ(ah, AR_Q_TXE),
460b7d5e03cSMatthew Dillon                                    OS_REG_READ(ah, AR_Q_TXD)
461b7d5e03cSMatthew Dillon                 );
462b7d5e03cSMatthew Dillon         for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
463b7d5e03cSMatthew Dillon             val = OS_REG_READ(ah, AR_QTXDP(i));
464b7d5e03cSMatthew Dillon             val2 = OS_REG_READ(ah, AR_QSTS(i)) & AR_Q_STS_PEND_FR_CNT;
465b7d5e03cSMatthew Dillon             HALDEBUG(ah, HAL_DEBUG_TXDESC, "[%d] %x %d\n", i, val, val2);
466b7d5e03cSMatthew Dillon         }
467b7d5e03cSMatthew Dillon         return;
468b7d5e03cSMatthew Dillon     }
469b7d5e03cSMatthew Dillon     if (mode == 8) {                      /* set TXE for qnum */
470b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_Q_TXE, 1 << qnum);
471b7d5e03cSMatthew Dillon         return;
472b7d5e03cSMatthew Dillon     }
473b7d5e03cSMatthew Dillon     if (mode == 9) {
474b7d5e03cSMatthew Dillon         prefetch = (int)ds;
475b7d5e03cSMatthew Dillon         return;
476b7d5e03cSMatthew Dillon     }
477b7d5e03cSMatthew Dillon 
478b7d5e03cSMatthew Dillon     if (mode >= 1) {                    /* initiate cont tx operation */
479b7d5e03cSMatthew Dillon         /* Disable AGC to A2 */
480b7d5e03cSMatthew Dillon         qnum = (int) ds;
481b7d5e03cSMatthew Dillon 
482b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_PHY_TEST,
483b7d5e03cSMatthew Dillon             (OS_REG_READ(ah, AR_PHY_TEST) | PHY_AGC_CLR) );
484b7d5e03cSMatthew Dillon 
485b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, 0x9864, OS_REG_READ(ah, 0x9864) | 0x7f000);
486b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, 0x9924, OS_REG_READ(ah, 0x9924) | 0x7f00fe);
487b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_DIAG_SW,
488b7d5e03cSMatthew Dillon             (OS_REG_READ(ah, AR_DIAG_SW) |
489b7d5e03cSMatthew Dillon              (AR_DIAG_FORCE_RX_CLEAR + AR_DIAG_IGNORE_VIRT_CS)) );
490b7d5e03cSMatthew Dillon 
491b7d5e03cSMatthew Dillon 
492b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     /* set receive disable */
493b7d5e03cSMatthew Dillon 
494b7d5e03cSMatthew Dillon         if (mode == 3 || mode == 4) {
495b7d5e03cSMatthew Dillon             int txcfg;
496b7d5e03cSMatthew Dillon 
497b7d5e03cSMatthew Dillon             if (mode == 3) {
498b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
499b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff);
500b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 100);
501b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 100);
502b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_TIME_OUT, 2);
503b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, 100);
504b7d5e03cSMatthew Dillon             }
505b7d5e03cSMatthew Dillon 
506b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff);
507b7d5e03cSMatthew Dillon             /* enable prefetch on qnum */
508b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_D_FPCTL, 0x10 | qnum);
509b7d5e03cSMatthew Dillon             txcfg = 5 | (6 << AR_FTRIG_S);
510b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_TXCFG, txcfg);
511b7d5e03cSMatthew Dillon 
512b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_QMISC(qnum),        /* set QCU modes */
513b7d5e03cSMatthew Dillon                          AR_Q_MISC_DCU_EARLY_TERM_REQ
514b7d5e03cSMatthew Dillon                          + AR_Q_MISC_FSP_ASAP
515b7d5e03cSMatthew Dillon                          + AR_Q_MISC_CBR_INCR_DIS1
516b7d5e03cSMatthew Dillon                          + AR_Q_MISC_CBR_INCR_DIS0
517b7d5e03cSMatthew Dillon                         );
518b7d5e03cSMatthew Dillon 
519b7d5e03cSMatthew Dillon             /* stop tx dma all all except qnum */
520b7d5e03cSMatthew Dillon             qbits = 0x3ff;
521b7d5e03cSMatthew Dillon             qbits &= ~(1 << qnum);
522b7d5e03cSMatthew Dillon             for (i = 0; i < 10; i++) {
523b7d5e03cSMatthew Dillon                 if (i == qnum) {
524b7d5e03cSMatthew Dillon                     continue;
525b7d5e03cSMatthew Dillon                 }
526b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_Q_TXD, 1 << i);
527b7d5e03cSMatthew Dillon             }
528b7d5e03cSMatthew Dillon 
529b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_Q_TXD, qbits);
530b7d5e03cSMatthew Dillon 
531b7d5e03cSMatthew Dillon             /* clear and freeze MIB counters */
532b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
533b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
534b7d5e03cSMatthew Dillon 
535b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_DMISC(qnum),
536b7d5e03cSMatthew Dillon                          (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
537b7d5e03cSMatthew Dillon                           AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
538b7d5e03cSMatthew Dillon                          + (AR_D_MISC_ARB_LOCKOUT_IGNORE)
539b7d5e03cSMatthew Dillon                          + (AR_D_MISC_POST_FR_BKOFF_DIS)
540b7d5e03cSMatthew Dillon                          + (AR_D_MISC_VIR_COL_HANDLING_IGNORE <<
541b7d5e03cSMatthew Dillon                             AR_D_MISC_VIR_COL_HANDLING_S));
542b7d5e03cSMatthew Dillon 
543b7d5e03cSMatthew Dillon             for (i = 0; i < HAL_NUM_TX_QUEUES + 2; i++) { /* disconnect QCUs */
544b7d5e03cSMatthew Dillon                 if (i == qnum) {
545b7d5e03cSMatthew Dillon                     continue;
546b7d5e03cSMatthew Dillon                 }
547b7d5e03cSMatthew Dillon                 OS_REG_WRITE(ah, AR_DQCUMASK(i), 0);
548b7d5e03cSMatthew Dillon             }
549b7d5e03cSMatthew Dillon         }
550b7d5e03cSMatthew Dillon     }
551b7d5e03cSMatthew Dillon     if (mode == 0) {
552b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_PHY_TEST,
553b7d5e03cSMatthew Dillon             (OS_REG_READ(ah, AR_PHY_TEST) & ~PHY_AGC_CLR));
554b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_DIAG_SW,
555b7d5e03cSMatthew Dillon             (OS_REG_READ(ah, AR_DIAG_SW) &
556b7d5e03cSMatthew Dillon              ~(AR_DIAG_FORCE_RX_CLEAR + AR_DIAG_IGNORE_VIRT_CS)));
557b7d5e03cSMatthew Dillon     }
558b7d5e03cSMatthew Dillon #endif
559b7d5e03cSMatthew Dillon }
560b7d5e03cSMatthew Dillon #endif
561b7d5e03cSMatthew Dillon 
562b7d5e03cSMatthew Dillon void
ar9300_set_paprd_tx_desc(struct ath_hal * ah,void * ds,int chain_num)563b7d5e03cSMatthew Dillon ar9300_set_paprd_tx_desc(struct ath_hal *ah, void *ds, int chain_num)
564b7d5e03cSMatthew Dillon {
565b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
566b7d5e03cSMatthew Dillon 
567b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= SM((1 << chain_num), AR_paprd_chain_mask);
568b7d5e03cSMatthew Dillon }
569b7d5e03cSMatthew Dillon HAL_STATUS
ar9300_is_tx_done(struct ath_hal * ah)570b7d5e03cSMatthew Dillon ar9300_is_tx_done(struct ath_hal *ah)
571b7d5e03cSMatthew Dillon {
572b7d5e03cSMatthew Dillon     struct ath_hal_9300 *ahp = AH9300(ah);
573b7d5e03cSMatthew Dillon     struct ar9300_txs *ads;
574b7d5e03cSMatthew Dillon 
575b7d5e03cSMatthew Dillon     ads = &ahp->ts_ring[ahp->ts_tail];
576b7d5e03cSMatthew Dillon 
577b7d5e03cSMatthew Dillon     if (ads->status8 & AR_tx_done) {
578b7d5e03cSMatthew Dillon         return HAL_OK;
579b7d5e03cSMatthew Dillon     }
580b7d5e03cSMatthew Dillon     return HAL_EINPROGRESS;
581b7d5e03cSMatthew Dillon }
582b7d5e03cSMatthew Dillon 
583b7d5e03cSMatthew Dillon void
ar9300_set_11n_tx_desc(struct ath_hal * ah,void * ds,u_int pkt_len,HAL_PKT_TYPE type,u_int tx_power,u_int key_ix,HAL_KEY_TYPE key_type,u_int flags)584b7d5e03cSMatthew Dillon ar9300_set_11n_tx_desc(
585b7d5e03cSMatthew Dillon     struct ath_hal *ah,
586b7d5e03cSMatthew Dillon     void *ds,
587b7d5e03cSMatthew Dillon     u_int pkt_len,
588b7d5e03cSMatthew Dillon     HAL_PKT_TYPE type,
589b7d5e03cSMatthew Dillon     u_int tx_power,
590b7d5e03cSMatthew Dillon     u_int key_ix,
591b7d5e03cSMatthew Dillon     HAL_KEY_TYPE key_type,
592b7d5e03cSMatthew Dillon     u_int flags)
593b7d5e03cSMatthew Dillon {
594b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
595b7d5e03cSMatthew Dillon     struct ath_hal_9300 *ahp = AH9300(ah);
596b7d5e03cSMatthew Dillon 
597b7d5e03cSMatthew Dillon     HALASSERT(is_valid_pkt_type(type));
598b7d5e03cSMatthew Dillon     HALASSERT(is_valid_key_type(key_type));
599b7d5e03cSMatthew Dillon 
600b7d5e03cSMatthew Dillon     tx_power += ahp->ah_tx_power_index_offset;
601b7d5e03cSMatthew Dillon     if (tx_power > 63) {
602b7d5e03cSMatthew Dillon         tx_power = 63;
603b7d5e03cSMatthew Dillon     }
604b7d5e03cSMatthew Dillon     ads->ds_ctl11 =
605b7d5e03cSMatthew Dillon         (pkt_len & AR_frame_len)
606b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_VMF ? AR_virt_more_frag : 0)
607b7d5e03cSMatthew Dillon       | SM(tx_power, AR_xmit_power0)
608b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_VEOL ? AR_veol : 0)
609b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_CLRDMASK ? AR_clr_dest_mask : 0)
610b7d5e03cSMatthew Dillon       | (key_ix != HAL_TXKEYIX_INVALID ? AR_dest_idx_valid : 0)
611b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_LOWRXCHAIN ? AR_low_rx_chain : 0);
612b7d5e03cSMatthew Dillon 
613b7d5e03cSMatthew Dillon     ads->ds_ctl12 =
614b7d5e03cSMatthew Dillon         (key_ix != HAL_TXKEYIX_INVALID ? SM(key_ix, AR_dest_idx) : 0)
615b7d5e03cSMatthew Dillon       | SM(type, AR_frame_type)
616b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_NOACK ? AR_no_ack : 0)
617b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_EXT_ONLY ? AR_ext_only : 0)
618b7d5e03cSMatthew Dillon       | (flags & HAL_TXDESC_EXT_AND_CTL ? AR_ext_and_ctl : 0);
619b7d5e03cSMatthew Dillon 
620b7d5e03cSMatthew Dillon     ads->ds_ctl17 =
621b7d5e03cSMatthew Dillon         SM(key_type, AR_encr_type) | (flags & HAL_TXDESC_LDPC ? AR_ldpc : 0);
622b7d5e03cSMatthew Dillon 
623b7d5e03cSMatthew Dillon     ads->ds_ctl18 = 0;
624b7d5e03cSMatthew Dillon     ads->ds_ctl19 = AR_not_sounding; /* set not sounding for normal frame */
625b7d5e03cSMatthew Dillon 
626b7d5e03cSMatthew Dillon 
627b7d5e03cSMatthew Dillon     /*
628b7d5e03cSMatthew Dillon      * Clear Ness1/2/3 (Number of Extension Spatial Streams) fields.
629b7d5e03cSMatthew Dillon      * Ness0 is cleared in ctl19.  See EV66059 (BB panic).
630b7d5e03cSMatthew Dillon      */
631b7d5e03cSMatthew Dillon     ads->ds_ctl20 = 0;
632b7d5e03cSMatthew Dillon     ads->ds_ctl21 = 0;
633b7d5e03cSMatthew Dillon     ads->ds_ctl22 = 0;
634b7d5e03cSMatthew Dillon }
635b7d5e03cSMatthew Dillon 
ar9300_set_rx_chainmask(struct ath_hal * ah,int rxchainmask)636b7d5e03cSMatthew Dillon void ar9300_set_rx_chainmask(struct ath_hal *ah, int rxchainmask)
637b7d5e03cSMatthew Dillon {
638b7d5e03cSMatthew Dillon     OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rxchainmask);
639b7d5e03cSMatthew Dillon }
640b7d5e03cSMatthew Dillon 
ar9300_update_loc_ctl_reg(struct ath_hal * ah,int pos_bit)641b7d5e03cSMatthew Dillon void ar9300_update_loc_ctl_reg(struct ath_hal *ah, int pos_bit)
642b7d5e03cSMatthew Dillon {
643b7d5e03cSMatthew Dillon     u_int32_t reg_val;
644b7d5e03cSMatthew Dillon     reg_val = OS_REG_READ(ah, AR_LOC_CTL_REG);
645b7d5e03cSMatthew Dillon     if (pos_bit) {
646b7d5e03cSMatthew Dillon         if (!(reg_val & AR_LOC_CTL_REG_FS)) {
647b7d5e03cSMatthew Dillon             /* set fast timestamp bit in the regiter */
648b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_LOC_CTL_REG, (reg_val | AR_LOC_CTL_REG_FS));
649b7d5e03cSMatthew Dillon             OS_REG_WRITE(ah, AR_LOC_TIMER_REG, 0);
650b7d5e03cSMatthew Dillon         }
651b7d5e03cSMatthew Dillon     }
652b7d5e03cSMatthew Dillon     else {
653b7d5e03cSMatthew Dillon         OS_REG_WRITE(ah, AR_LOC_CTL_REG, (reg_val & ~AR_LOC_CTL_REG_FS));
654b7d5e03cSMatthew Dillon     }
655b7d5e03cSMatthew Dillon }
656b7d5e03cSMatthew Dillon 
657b7d5e03cSMatthew Dillon #if 0
658b7d5e03cSMatthew Dillon #define HT_RC_2_MCS(_rc)        ((_rc) & 0x0f)
659b7d5e03cSMatthew Dillon static const u_int8_t ba_duration_delta[] = {
660b7d5e03cSMatthew Dillon     24,     /*  0: BPSK       */
661b7d5e03cSMatthew Dillon     12,     /*  1: QPSK 1/2   */
662b7d5e03cSMatthew Dillon     12,     /*  2: QPSK 3/4   */
663b7d5e03cSMatthew Dillon      4,     /*  3: 16-QAM 1/2 */
664b7d5e03cSMatthew Dillon      4,     /*  4: 16-QAM 3/4 */
665b7d5e03cSMatthew Dillon      4,     /*  5: 64-QAM 2/3 */
666b7d5e03cSMatthew Dillon      4,     /*  6: 64-QAM 3/4 */
667b7d5e03cSMatthew Dillon      4,     /*  7: 64-QAM 5/6 */
668b7d5e03cSMatthew Dillon     24,     /*  8: BPSK       */
669b7d5e03cSMatthew Dillon     12,     /*  9: QPSK 1/2   */
670b7d5e03cSMatthew Dillon     12,     /* 10: QPSK 3/4   */
671b7d5e03cSMatthew Dillon      4,     /* 11: 16-QAM 1/2 */
672b7d5e03cSMatthew Dillon      4,     /* 12: 16-QAM 3/4 */
673b7d5e03cSMatthew Dillon      4,     /* 13: 64-QAM 2/3 */
674b7d5e03cSMatthew Dillon      4,     /* 14: 64-QAM 3/4 */
675b7d5e03cSMatthew Dillon      4,     /* 15: 64-QAM 5/6 */
676b7d5e03cSMatthew Dillon };
677b7d5e03cSMatthew Dillon #endif
678b7d5e03cSMatthew Dillon 
679b7d5e03cSMatthew Dillon 
680b7d5e03cSMatthew Dillon static u_int8_t
ar9300_get_tx_mode(u_int rate_flags)681b7d5e03cSMatthew Dillon ar9300_get_tx_mode(u_int rate_flags)
682b7d5e03cSMatthew Dillon {
683b7d5e03cSMatthew Dillon 
684b7d5e03cSMatthew Dillon     /* Check whether STBC is enabled if TxBF is not enabled */
685b7d5e03cSMatthew Dillon     if (rate_flags & HAL_RATESERIES_STBC){
686b7d5e03cSMatthew Dillon         return AR9300_STBC_MODE;
687b7d5e03cSMatthew Dillon     }
688b7d5e03cSMatthew Dillon     return AR9300_DEF_MODE;
689b7d5e03cSMatthew Dillon }
690b7d5e03cSMatthew Dillon void
ar9300_set_11n_rate_scenario(struct ath_hal * ah,void * ds,void * lastds,u_int dur_update_en,u_int rts_cts_rate,u_int rts_cts_duration,HAL_11N_RATE_SERIES series[],u_int nseries,u_int flags,u_int32_t smart_antenna)691b7d5e03cSMatthew Dillon ar9300_set_11n_rate_scenario(
692b7d5e03cSMatthew Dillon     struct ath_hal *ah,
693b7d5e03cSMatthew Dillon     void *ds,
694b7d5e03cSMatthew Dillon     void *lastds,
695b7d5e03cSMatthew Dillon     u_int dur_update_en,
696b7d5e03cSMatthew Dillon     u_int rts_cts_rate,
697b7d5e03cSMatthew Dillon     u_int rts_cts_duration,
698b7d5e03cSMatthew Dillon     HAL_11N_RATE_SERIES series[],
699b7d5e03cSMatthew Dillon     u_int nseries,
700b7d5e03cSMatthew Dillon     u_int flags,
701b7d5e03cSMatthew Dillon     u_int32_t smart_antenna)
702b7d5e03cSMatthew Dillon {
703b7d5e03cSMatthew Dillon     struct ath_hal_private *ap = AH_PRIVATE(ah);
704b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
705b7d5e03cSMatthew Dillon     struct ar9300_txc *last_ads = AR9300TXC(lastds);
706b7d5e03cSMatthew Dillon     u_int32_t ds_ctl11;
707b7d5e03cSMatthew Dillon     u_int8_t ant, cal_pkt = 0;
708b7d5e03cSMatthew Dillon     u_int mode, tx_mode = AR9300_DEF_MODE;
709b7d5e03cSMatthew Dillon 
710b7d5e03cSMatthew Dillon     HALASSERT(nseries == 4);
711b7d5e03cSMatthew Dillon     (void)nseries;
712b7d5e03cSMatthew Dillon     (void)rts_cts_duration;   /* use H/W to calculate RTSCTSDuration */
713b7d5e03cSMatthew Dillon 
714b7d5e03cSMatthew Dillon     ds_ctl11 = ads->ds_ctl11;
715b7d5e03cSMatthew Dillon     /*
716b7d5e03cSMatthew Dillon      * Rate control settings override
717b7d5e03cSMatthew Dillon      */
718b7d5e03cSMatthew Dillon     if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
719b7d5e03cSMatthew Dillon         if (flags & HAL_TXDESC_RTSENA) {
720b7d5e03cSMatthew Dillon             ds_ctl11 &= ~AR_cts_enable;
721b7d5e03cSMatthew Dillon             ds_ctl11 |= AR_rts_enable;
722b7d5e03cSMatthew Dillon         } else {
723b7d5e03cSMatthew Dillon             ds_ctl11 &= ~AR_rts_enable;
724b7d5e03cSMatthew Dillon             ds_ctl11 |= AR_cts_enable;
725b7d5e03cSMatthew Dillon         }
726b7d5e03cSMatthew Dillon     } else {
727b7d5e03cSMatthew Dillon         ds_ctl11 = (ds_ctl11 & ~(AR_rts_enable | AR_cts_enable));
728b7d5e03cSMatthew Dillon     }
729b7d5e03cSMatthew Dillon 
730b7d5e03cSMatthew Dillon     mode = ath_hal_get_curmode(ah, ap->ah_curchan);
731b7d5e03cSMatthew Dillon     cal_pkt = (ads->ds_ctl12 & AR_paprd_chain_mask)?1:0;
732b7d5e03cSMatthew Dillon 
733b7d5e03cSMatthew Dillon     if (ah->ah_config.ath_hal_desc_tpc) {
734b7d5e03cSMatthew Dillon         int16_t txpower;
735b7d5e03cSMatthew Dillon 
736b7d5e03cSMatthew Dillon         if (!cal_pkt) {
737b7d5e03cSMatthew Dillon             /* Series 0 TxPower */
738b7d5e03cSMatthew Dillon             tx_mode = ar9300_get_tx_mode(series[0].RateFlags);
739b7d5e03cSMatthew Dillon             txpower = ar9300_get_rate_txpower(ah, mode, series[0].RateIndex,
740b7d5e03cSMatthew Dillon                                        series[0].ChSel, tx_mode);
741b7d5e03cSMatthew Dillon         } else {
742b7d5e03cSMatthew Dillon             txpower = AH9300(ah)->paprd_training_power;
743b7d5e03cSMatthew Dillon         }
744b7d5e03cSMatthew Dillon         ds_ctl11 &= ~AR_xmit_power0;
745b7d5e03cSMatthew Dillon         ds_ctl11 |=
746b7d5e03cSMatthew Dillon             set_11n_tx_power(0, AH_MIN(txpower, series[0].tx_power_cap));
747b7d5e03cSMatthew Dillon     }
748b7d5e03cSMatthew Dillon 
749b7d5e03cSMatthew Dillon     ads->ds_ctl11 = ds_ctl11;
750b7d5e03cSMatthew Dillon 
751b7d5e03cSMatthew Dillon 
752b7d5e03cSMatthew Dillon     ads->ds_ctl13 = set_11n_tries(series, 0)
753b7d5e03cSMatthew Dillon                              |  set_11n_tries(series, 1)
754b7d5e03cSMatthew Dillon                              |  set_11n_tries(series, 2)
755b7d5e03cSMatthew Dillon                              |  set_11n_tries(series, 3)
756b7d5e03cSMatthew Dillon                              |  (dur_update_en ? AR_dur_update_ena : 0)
757b7d5e03cSMatthew Dillon                              |  SM(0, AR_burst_dur);
758b7d5e03cSMatthew Dillon 
759b7d5e03cSMatthew Dillon     ads->ds_ctl14 = set_11n_rate(series, 0)
760b7d5e03cSMatthew Dillon                              |  set_11n_rate(series, 1)
761b7d5e03cSMatthew Dillon                              |  set_11n_rate(series, 2)
762b7d5e03cSMatthew Dillon                              |  set_11n_rate(series, 3);
763b7d5e03cSMatthew Dillon 
764b7d5e03cSMatthew Dillon     ads->ds_ctl15 = set_11n_pkt_dur_rts_cts(series, 0)
765b7d5e03cSMatthew Dillon                              |  set_11n_pkt_dur_rts_cts(series, 1);
766b7d5e03cSMatthew Dillon 
767b7d5e03cSMatthew Dillon     ads->ds_ctl16 = set_11n_pkt_dur_rts_cts(series, 2)
768b7d5e03cSMatthew Dillon                              |  set_11n_pkt_dur_rts_cts(series, 3);
769b7d5e03cSMatthew Dillon 
770b7d5e03cSMatthew Dillon     ads->ds_ctl18 = set_11n_rate_flags(series, 0)
771b7d5e03cSMatthew Dillon                              |  set_11n_rate_flags(series, 1)
772b7d5e03cSMatthew Dillon                              |  set_11n_rate_flags(series, 2)
773b7d5e03cSMatthew Dillon                              |  set_11n_rate_flags(series, 3)
774b7d5e03cSMatthew Dillon                              | SM(rts_cts_rate, AR_rts_cts_rate);
775b7d5e03cSMatthew Dillon     /* set not sounding for normal frame */
776b7d5e03cSMatthew Dillon     ads->ds_ctl19 = AR_not_sounding;
777b7d5e03cSMatthew Dillon 
778b7d5e03cSMatthew Dillon     if (ah->ah_config.ath_hal_desc_tpc) {
779b7d5e03cSMatthew Dillon         int16_t txpower;
780b7d5e03cSMatthew Dillon 
781b7d5e03cSMatthew Dillon         if (!cal_pkt) {
782b7d5e03cSMatthew Dillon             /* Series 1 TxPower */
783b7d5e03cSMatthew Dillon             tx_mode = ar9300_get_tx_mode(series[1].RateFlags);
784b7d5e03cSMatthew Dillon             txpower = ar9300_get_rate_txpower(
785b7d5e03cSMatthew Dillon                 ah, mode, series[1].RateIndex, series[1].ChSel, tx_mode);
786b7d5e03cSMatthew Dillon         } else {
787b7d5e03cSMatthew Dillon             txpower = AH9300(ah)->paprd_training_power;
788b7d5e03cSMatthew Dillon         }
789b7d5e03cSMatthew Dillon         ads->ds_ctl20 |=
790b7d5e03cSMatthew Dillon             set_11n_tx_power(1, AH_MIN(txpower, series[1].tx_power_cap));
791b7d5e03cSMatthew Dillon 
792b7d5e03cSMatthew Dillon 
793b7d5e03cSMatthew Dillon         /* Series 2 TxPower */
794b7d5e03cSMatthew Dillon         if (!cal_pkt) {
795b7d5e03cSMatthew Dillon             tx_mode = ar9300_get_tx_mode(series[2].RateFlags);
796b7d5e03cSMatthew Dillon             txpower = ar9300_get_rate_txpower(
797b7d5e03cSMatthew Dillon                 ah, mode, series[2].RateIndex, series[2].ChSel, tx_mode);
798b7d5e03cSMatthew Dillon         } else {
799b7d5e03cSMatthew Dillon             txpower = AH9300(ah)->paprd_training_power;
800b7d5e03cSMatthew Dillon         }
801b7d5e03cSMatthew Dillon         ads->ds_ctl21 |=
802b7d5e03cSMatthew Dillon             set_11n_tx_power(2, AH_MIN(txpower, series[2].tx_power_cap));
803b7d5e03cSMatthew Dillon 
804b7d5e03cSMatthew Dillon         /* Series 3 TxPower */
805b7d5e03cSMatthew Dillon         if (!cal_pkt) {
806b7d5e03cSMatthew Dillon             tx_mode = ar9300_get_tx_mode(series[3].RateFlags);
807b7d5e03cSMatthew Dillon             txpower = ar9300_get_rate_txpower(
808b7d5e03cSMatthew Dillon                 ah, mode, series[3].RateIndex, series[3].ChSel, tx_mode);
809b7d5e03cSMatthew Dillon         } else {
810b7d5e03cSMatthew Dillon             txpower = AH9300(ah)->paprd_training_power;
811b7d5e03cSMatthew Dillon         }
812b7d5e03cSMatthew Dillon         ads->ds_ctl22 |=
813b7d5e03cSMatthew Dillon             set_11n_tx_power(3, AH_MIN(txpower, series[3].tx_power_cap));
814b7d5e03cSMatthew Dillon     }
815b7d5e03cSMatthew Dillon 
816b7d5e03cSMatthew Dillon     if (smart_antenna != 0xffffffff)
817b7d5e03cSMatthew Dillon     {
818b7d5e03cSMatthew Dillon         /* TX DESC dword 19 to 23 are used for smart antenna configuaration
819b7d5e03cSMatthew Dillon          * ctl19 for rate series 0 ... ctrl22 for series 3
820b7d5e03cSMatthew Dillon          * bits[2:0] used to configure smart anntenna
821b7d5e03cSMatthew Dillon          */
822b7d5e03cSMatthew Dillon         ant = (smart_antenna&0x000000ff);
823b7d5e03cSMatthew Dillon         ads->ds_ctl19 |= ant; /* rateseries 0 */
824b7d5e03cSMatthew Dillon 
825b7d5e03cSMatthew Dillon         ant = (smart_antenna&0x0000ff00) >> 8;
826b7d5e03cSMatthew Dillon         ads->ds_ctl20 |= ant;  /* rateseries 1 */
827b7d5e03cSMatthew Dillon 
828b7d5e03cSMatthew Dillon         ant = (smart_antenna&0x00ff0000) >> 16;
829b7d5e03cSMatthew Dillon         ads->ds_ctl21 |= ant;  /* rateseries 2 */
830b7d5e03cSMatthew Dillon 
831b7d5e03cSMatthew Dillon         ant = (smart_antenna&0xff000000) >> 24;
832b7d5e03cSMatthew Dillon         ads->ds_ctl22 |= ant;  /* rateseries 3 */
833b7d5e03cSMatthew Dillon     }
834b7d5e03cSMatthew Dillon 
835b7d5e03cSMatthew Dillon #ifdef AH_NEED_DESC_SWAP
836b7d5e03cSMatthew Dillon     last_ads->ds_ctl13 = __bswap32(ads->ds_ctl13);
837b7d5e03cSMatthew Dillon     last_ads->ds_ctl14 = __bswap32(ads->ds_ctl14);
838b7d5e03cSMatthew Dillon #else
839b7d5e03cSMatthew Dillon     last_ads->ds_ctl13 = ads->ds_ctl13;
840b7d5e03cSMatthew Dillon     last_ads->ds_ctl14 = ads->ds_ctl14;
841b7d5e03cSMatthew Dillon #endif
842b7d5e03cSMatthew Dillon }
843b7d5e03cSMatthew Dillon 
844b7d5e03cSMatthew Dillon void
ar9300_set_11n_aggr_first(struct ath_hal * ah,struct ath_desc * ds,u_int aggr_len,u_int num_delims)845b7d5e03cSMatthew Dillon ar9300_set_11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
846b7d5e03cSMatthew Dillon   u_int aggr_len, u_int num_delims)
847b7d5e03cSMatthew Dillon {
848b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
849b7d5e03cSMatthew Dillon 
850b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= (AR_is_aggr | AR_more_aggr);
851b7d5e03cSMatthew Dillon 
852b7d5e03cSMatthew Dillon     ads->ds_ctl17 &= ~AR_aggr_len;
853b7d5e03cSMatthew Dillon     ads->ds_ctl17 &= ~AR_pad_delim;
854b7d5e03cSMatthew Dillon     /* XXX should use a stack variable! */
855b7d5e03cSMatthew Dillon     ads->ds_ctl17 |= SM(aggr_len, AR_aggr_len);
856b7d5e03cSMatthew Dillon     ads->ds_ctl17 |= SM(num_delims, AR_pad_delim);
857b7d5e03cSMatthew Dillon }
858b7d5e03cSMatthew Dillon 
859b7d5e03cSMatthew Dillon void
ar9300_set_11n_aggr_middle(struct ath_hal * ah,struct ath_desc * ds,u_int num_delims)860b7d5e03cSMatthew Dillon ar9300_set_11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
861b7d5e03cSMatthew Dillon   u_int num_delims)
862b7d5e03cSMatthew Dillon {
863b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
864b7d5e03cSMatthew Dillon     unsigned int ctl17;
865b7d5e03cSMatthew Dillon 
866b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= (AR_is_aggr | AR_more_aggr);
867b7d5e03cSMatthew Dillon 
868b7d5e03cSMatthew Dillon     /*
869b7d5e03cSMatthew Dillon      * We use a stack variable to manipulate ctl6 to reduce uncached
870b7d5e03cSMatthew Dillon      * read modify, modfiy, write.
871b7d5e03cSMatthew Dillon      */
872b7d5e03cSMatthew Dillon     ctl17 = ads->ds_ctl17;
873b7d5e03cSMatthew Dillon     ctl17 &= ~AR_pad_delim;
874b7d5e03cSMatthew Dillon     ctl17 |= SM(num_delims, AR_pad_delim);
875b7d5e03cSMatthew Dillon     ads->ds_ctl17 = ctl17;
876b7d5e03cSMatthew Dillon }
877b7d5e03cSMatthew Dillon 
878b7d5e03cSMatthew Dillon void
ar9300_set_11n_aggr_last(struct ath_hal * ah,struct ath_desc * ds)879b7d5e03cSMatthew Dillon ar9300_set_11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
880b7d5e03cSMatthew Dillon {
881b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
882b7d5e03cSMatthew Dillon 
883b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= AR_is_aggr;
884b7d5e03cSMatthew Dillon     ads->ds_ctl12 &= ~AR_more_aggr;
885b7d5e03cSMatthew Dillon     ads->ds_ctl17 &= ~AR_pad_delim;
886b7d5e03cSMatthew Dillon }
887b7d5e03cSMatthew Dillon 
888b7d5e03cSMatthew Dillon void
ar9300_clr_11n_aggr(struct ath_hal * ah,struct ath_desc * ds)889b7d5e03cSMatthew Dillon ar9300_clr_11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
890b7d5e03cSMatthew Dillon {
891b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
892b7d5e03cSMatthew Dillon 
893b7d5e03cSMatthew Dillon     ads->ds_ctl12 &= (~AR_is_aggr & ~AR_more_aggr);
894b7d5e03cSMatthew Dillon }
895b7d5e03cSMatthew Dillon 
896b7d5e03cSMatthew Dillon void
ar9300_set_11n_burst_duration(struct ath_hal * ah,struct ath_desc * ds,u_int burst_duration)897b7d5e03cSMatthew Dillon ar9300_set_11n_burst_duration(struct ath_hal *ah, struct ath_desc *ds,
898b7d5e03cSMatthew Dillon     u_int burst_duration)
899b7d5e03cSMatthew Dillon {
900b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
901b7d5e03cSMatthew Dillon 
902b7d5e03cSMatthew Dillon     ads->ds_ctl13 &= ~AR_burst_dur;
903b7d5e03cSMatthew Dillon     ads->ds_ctl13 |= SM(burst_duration, AR_burst_dur);
904b7d5e03cSMatthew Dillon }
905b7d5e03cSMatthew Dillon 
906b7d5e03cSMatthew Dillon void
ar9300_set_11n_rifs_burst_middle(struct ath_hal * ah,void * ds)907b7d5e03cSMatthew Dillon ar9300_set_11n_rifs_burst_middle(struct ath_hal *ah, void *ds)
908b7d5e03cSMatthew Dillon {
909b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
910b7d5e03cSMatthew Dillon 
911b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= AR_more_rifs | AR_no_ack;
912b7d5e03cSMatthew Dillon }
913b7d5e03cSMatthew Dillon 
914b7d5e03cSMatthew Dillon void
ar9300_set_11n_rifs_burst_last(struct ath_hal * ah,void * ds)915b7d5e03cSMatthew Dillon ar9300_set_11n_rifs_burst_last(struct ath_hal *ah, void *ds)
916b7d5e03cSMatthew Dillon {
917b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
918b7d5e03cSMatthew Dillon 
919b7d5e03cSMatthew Dillon     ads->ds_ctl12 &= (~AR_more_aggr & ~AR_more_rifs);
920b7d5e03cSMatthew Dillon }
921b7d5e03cSMatthew Dillon 
922b7d5e03cSMatthew Dillon void
ar9300_clr_11n_rifs_burst(struct ath_hal * ah,void * ds)923b7d5e03cSMatthew Dillon ar9300_clr_11n_rifs_burst(struct ath_hal *ah, void *ds)
924b7d5e03cSMatthew Dillon {
925b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
926b7d5e03cSMatthew Dillon 
927b7d5e03cSMatthew Dillon     ads->ds_ctl12 &= (~AR_more_rifs & ~AR_no_ack);
928b7d5e03cSMatthew Dillon }
929b7d5e03cSMatthew Dillon 
930b7d5e03cSMatthew Dillon void
ar9300_set_11n_aggr_rifs_burst(struct ath_hal * ah,void * ds)931b7d5e03cSMatthew Dillon ar9300_set_11n_aggr_rifs_burst(struct ath_hal *ah, void *ds)
932b7d5e03cSMatthew Dillon {
933b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
934b7d5e03cSMatthew Dillon 
935b7d5e03cSMatthew Dillon     ads->ds_ctl12 |= AR_no_ack;
936b7d5e03cSMatthew Dillon     ads->ds_ctl12 &= ~AR_more_rifs;
937b7d5e03cSMatthew Dillon }
938b7d5e03cSMatthew Dillon 
939b7d5e03cSMatthew Dillon void
ar9300_set_11n_virtual_more_frag(struct ath_hal * ah,struct ath_desc * ds,u_int vmf)940b7d5e03cSMatthew Dillon ar9300_set_11n_virtual_more_frag(struct ath_hal *ah, struct ath_desc *ds,
941b7d5e03cSMatthew Dillon                                                   u_int vmf)
942b7d5e03cSMatthew Dillon {
943b7d5e03cSMatthew Dillon     struct ar9300_txc *ads = AR9300TXC(ds);
944b7d5e03cSMatthew Dillon 
945b7d5e03cSMatthew Dillon     if (vmf) {
946b7d5e03cSMatthew Dillon         ads->ds_ctl11 |=  AR_virt_more_frag;
947b7d5e03cSMatthew Dillon     } else {
948b7d5e03cSMatthew Dillon         ads->ds_ctl11 &= ~AR_virt_more_frag;
949b7d5e03cSMatthew Dillon     }
950b7d5e03cSMatthew Dillon }
951b7d5e03cSMatthew Dillon 
952b7d5e03cSMatthew Dillon void
ar9300_get_desc_info(struct ath_hal * ah,HAL_DESC_INFO * desc_info)953b7d5e03cSMatthew Dillon ar9300_get_desc_info(struct ath_hal *ah, HAL_DESC_INFO *desc_info)
954b7d5e03cSMatthew Dillon {
955b7d5e03cSMatthew Dillon     desc_info->txctl_numwords = TXCTL_NUMWORDS(ah);
956b7d5e03cSMatthew Dillon     desc_info->txctl_offset = TXCTL_OFFSET(ah);
957b7d5e03cSMatthew Dillon     desc_info->txstatus_numwords = TXSTATUS_NUMWORDS(ah);
958b7d5e03cSMatthew Dillon     desc_info->txstatus_offset = TXSTATUS_OFFSET(ah);
959b7d5e03cSMatthew Dillon 
960b7d5e03cSMatthew Dillon     desc_info->rxctl_numwords = RXCTL_NUMWORDS(ah);
961b7d5e03cSMatthew Dillon     desc_info->rxctl_offset = RXCTL_OFFSET(ah);
962b7d5e03cSMatthew Dillon     desc_info->rxstatus_numwords = RXSTATUS_NUMWORDS(ah);
963b7d5e03cSMatthew Dillon     desc_info->rxstatus_offset = RXSTATUS_OFFSET(ah);
964b7d5e03cSMatthew Dillon }
965