use ah_getRateTable directly
[open-ath9k-htc-firmware.git] / target_firmware / wlan / if_ath.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted (subject to the limitations in the
7  * disclaimer below) provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *  * Neither the name of Qualcomm Atheros nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22  * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 #include <adf_os_types.h>
37 #include <adf_os_pci.h>
38 #include <adf_os_dma.h>
39 #include <adf_os_timer.h>
40 #include <adf_os_lock.h>
41 #include <adf_os_io.h>
42 #include <adf_os_mem.h>
43 #include <adf_os_util.h>
44 #include <adf_os_stdtypes.h>
45 #include <adf_os_defer.h>
46 #include <adf_os_atomic.h>
47 #include <adf_nbuf.h>
48 #include <adf_net.h>
49 #include <adf_net_wcmd.h>
50 #include <adf_os_irq.h>
51
52 #include <if_ath_pci.h>
53 #include "if_llc.h"
54 #include "ieee80211_var.h"
55 #include "if_athrate.h"
56 #include "if_athvar.h"
57 #include "ah_desc.h"
58 #include "ah.h"
59
60 static a_int32_t ath_numrxbufs = -1;
61 static a_int32_t ath_numrxdescs = -1;
62
63 #if defined(PROJECT_MAGPIE)
64 uint32_t *init_htc_handle = 0;
65 #endif
66
67 #define RX_ENDPOINT_ID 3
68 #define ATH_CABQ_HANDLING_THRESHOLD 9000
69 #define UAPSDQ_NUM   9
70 #define CABQ_NUM     8
71
72 void owl_tgt_tx_tasklet(TQUEUE_ARG data);
73 static void ath_tgt_send_beacon(struct ath_softc_tgt *sc,adf_nbuf_t bc_hdr,adf_nbuf_t nbuf,HTC_ENDPOINT_ID EndPt);
74 static void ath_hal_reg_write_tgt(void *Context, A_UINT16 Command, A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen);
75 extern struct ath_tx_buf* ath_tgt_tx_prepare(struct ath_softc_tgt *sc, adf_nbuf_t skb, ath_data_hdr_t *dh);
76 extern void  ath_tgt_send_mgt(struct ath_softc_tgt *sc,adf_nbuf_t mgt_hdr, adf_nbuf_t skb,HTC_ENDPOINT_ID EndPt);
77 extern HAL_BOOL ath_hal_wait(struct ath_hal *ah, a_uint32_t reg, a_uint32_t mask, a_uint32_t val);
78 extern void owltgt_tx_processq(struct ath_softc_tgt *sc, struct ath_txq *txq,  owl_txq_state_t txqstate);
79 void owl_tgt_node_init(struct ath_node_target * an);
80 void ath_tgt_tx_sched_normal(struct ath_softc_tgt *sc, struct ath_buf *bf);
81 void ath_tgt_tx_sched_nonaggr(struct ath_softc_tgt *sc,struct ath_buf * bf_host);
82
83 /*************/
84 /* Utilities */
85 /*************/
86
87 #undef adf_os_cpu_to_le16
88
89 static a_uint16_t adf_os_cpu_to_le16(a_uint16_t x)
90 {
91         return ((((x) & 0xff00) >> 8) |   (((x) & 0x00ff) << 8));
92 }
93
94 /*
95  * Extend a 32 bit TSF to 64 bit, taking wrapping into account.
96  */
97 static u_int64_t ath_extend_tsf(struct ath_softc_tgt *sc, u_int32_t rstamp)
98 {
99         u_int64_t tsf;
100         u_int32_t tsf_low;
101         u_int64_t tsf64;
102
103         tsf = ath_hal_gettsf64(sc->sc_ah);
104         tsf_low = tsf & 0xffffffff;
105         tsf64 = (tsf & ~0xffffffffULL) | rstamp;
106
107         if (rstamp > tsf_low && (rstamp - tsf_low > 0x10000000))
108                 tsf64 -= 0x100000000ULL;
109
110         if (rstamp < tsf_low && (tsf_low - rstamp > 0x10000000))
111                 tsf64 += 0x100000000ULL;
112
113         return tsf64;
114 }
115
116 static a_int32_t ath_rate_setup(struct ath_softc_tgt *sc, a_uint32_t mode)
117 {
118         struct ath_hal *ah = sc->sc_ah;
119         const HAL_RATE_TABLE *rt;
120
121         switch (mode) {
122         case IEEE80211_MODE_11NA:
123                 sc->sc_rates[mode] = ah->ah_getRateTable(ah, HAL_MODE_11NA);
124                 break;
125         case IEEE80211_MODE_11NG:
126                 sc->sc_rates[mode] = ah->ah_getRateTable(ah, HAL_MODE_11NG);
127                 break;
128         default:
129                 return 0;
130         }
131         rt = sc->sc_rates[mode];
132         if (rt == NULL)
133                 return 0;
134
135         return 1;
136 }
137
138 static void ath_setcurmode(struct ath_softc_tgt *sc,
139                            enum ieee80211_phymode mode)
140 {
141         const HAL_RATE_TABLE *rt;
142         a_int32_t i;
143
144         adf_os_mem_set(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
145
146         rt = sc->sc_rates[mode];
147         adf_os_assert(rt != NULL);
148
149         for (i = 0; i < rt->rateCount; i++) {
150                 sc->sc_rixmap[rt->info[i].rateCode] = i;
151         }
152
153         sc->sc_currates = rt;
154         sc->sc_curmode = mode;
155         sc->sc_protrix = ((mode == IEEE80211_MODE_11NG) ? 3 : 0);
156
157 }
158
159 void wmi_event(wmi_handle_t handle, WMI_EVENT_ID evt_id,
160                void *buffer, a_int32_t Length)
161 {
162         adf_nbuf_t netbuf = ADF_NBUF_NULL;
163         a_uint8_t *pData;
164
165         netbuf = WMI_AllocEvent(handle, WMI_EVT_CLASS_CMD_EVENT,
166                                 sizeof(WMI_CMD_HDR) + Length);
167
168         if (netbuf == ADF_NBUF_NULL) {
169                 adf_os_print("Buf null\n");
170                 return;
171         }
172
173         if (buffer != NULL && Length != 0 && Length < WMI_SVC_MAX_BUFFERED_EVENT_SIZE) {
174                 pData = adf_nbuf_put_tail(netbuf, Length);
175                 adf_os_mem_copy(pData, buffer, Length);
176         }
177
178         WMI_SendEvent(handle, netbuf, evt_id, 0, Length);
179 }
180
181 void wmi_cmd_rsp(void *pContext, WMI_COMMAND_ID cmd_id, A_UINT16 SeqNo,
182                  void *buffer, a_int32_t Length)
183 {
184         adf_nbuf_t netbuf = ADF_NBUF_NULL;
185         A_UINT8 *pData;
186
187         netbuf = WMI_AllocEvent(pContext, WMI_EVT_CLASS_CMD_REPLY,
188                                 sizeof(WMI_CMD_HDR) + Length);
189
190         if (netbuf == ADF_NBUF_NULL) {
191                 adf_os_assert(0);
192                 return;
193         }
194
195         if (Length != 0 && buffer != NULL) {
196                 pData = (A_UINT8 *)adf_nbuf_put_tail(netbuf, Length);
197                 adf_os_mem_copy(pData, buffer, Length);
198         }
199
200         WMI_SendEvent(pContext, netbuf, cmd_id, SeqNo, Length);
201 }
202
203 static void ath_node_vdelete_tgt(struct ath_softc_tgt *sc, a_uint8_t vap_index)
204 {
205         a_int32_t i;
206
207         for (i = 0; i < TARGET_NODE_MAX; i++) {
208                 if(sc->sc_sta[i].ni.ni_vapindex == vap_index)
209                         sc->sc_sta[i].an_valid = 0;
210         }
211 }
212
213 a_uint8_t ath_get_minrateidx(struct ath_softc_tgt *sc, struct ath_vap_target *avp)
214 {
215         if (sc->sc_curmode == IEEE80211_MODE_11NG)
216                 return avp->av_minrateidx[0];
217         else if (sc->sc_curmode == IEEE80211_MODE_11NA)
218                 return avp->av_minrateidx[1];
219
220         return 0;
221 }
222
223 /******/
224 /* RX */
225 /******/
226
227 static adf_nbuf_t ath_alloc_skb_align(struct ath_softc_tgt *sc,
228                                       a_uint32_t size, a_uint32_t align)
229 {
230         adf_nbuf_t skb;
231
232         skb = BUF_Pool_alloc_buf_align(sc->pool_handle, POOL_ID_WLAN_RX_BUF,
233                                        RX_HEADER_SPACE, align);
234         return skb;
235 }
236
237 static a_int32_t ath_rxdesc_init(struct ath_softc_tgt *sc, struct ath_rx_desc *ds)
238 {
239         struct ath_hal *ah = sc->sc_ah;
240         struct ath_rx_desc *ds_held;
241         a_uint8_t *anbdata;
242         a_uint32_t anblen;
243
244         if (!sc->sc_rxdesc_held) {
245                 sc->sc_rxdesc_held = ds;
246                 return 0;
247         }
248
249         ds_held = sc->sc_rxdesc_held;
250         sc->sc_rxdesc_held = ds;
251         ds = ds_held;
252
253         if (ds->ds_nbuf == ADF_NBUF_NULL) {
254                 ds->ds_nbuf = ath_alloc_skb_align(sc, sc->sc_rxbufsize, sc->sc_cachelsz);
255                 if (ds->ds_nbuf == ADF_NBUF_NULL) {
256                         sc->sc_rxdesc_held = ds;
257                         sc->sc_rx_stats.ast_rx_nobuf++;
258                         return ENOMEM;
259                 }
260                 adf_nbuf_map(sc->sc_dev, ds->ds_dmap, ds->ds_nbuf, ADF_OS_DMA_FROM_DEVICE);
261                 adf_nbuf_dmamap_info(ds->ds_dmap, &ds->ds_dmap_info);
262                 ds->ds_data = ds->ds_dmap_info.dma_segs[0].paddr;
263         }
264
265         ds->ds_link = 0;
266         adf_nbuf_peek_header(ds->ds_nbuf, &anbdata, &anblen);
267
268         ath_hal_setuprxdesc(ah, ds,
269                             adf_nbuf_tailroom(ds->ds_nbuf),
270                             0);
271
272         if (sc->sc_rxlink == NULL) {
273                 ath_hal_putrxbuf(ah, ds->ds_daddr);
274         }
275         else {
276                 *sc->sc_rxlink = ds->ds_daddr;
277         }
278         sc->sc_rxlink = &ds->ds_link;
279         ath_hal_rxena(ah);
280
281         return 0;
282 }
283
284 static void ath_rx_complete(struct ath_softc_tgt *sc, adf_nbuf_t buf)
285 {
286         struct ath_rx_desc *ds;
287         adf_nbuf_t buf_tmp;
288         adf_nbuf_queue_t nbuf_head;
289
290         adf_nbuf_split_to_frag(buf, &nbuf_head);
291         ds = asf_tailq_first(&sc->sc_rxdesc_idle);
292
293         while (ds) {
294                 struct ath_rx_desc *ds_tmp;
295                 buf_tmp = adf_nbuf_queue_remove(&nbuf_head);
296
297                 if (buf_tmp == NULL) {
298                         break;
299                 }
300
301                 BUF_Pool_free_buf(sc->pool_handle, POOL_ID_WLAN_RX_BUF, buf_tmp);
302
303                 ds_tmp = ds;
304                 ds = asf_tailq_next(ds, ds_list);
305
306                 ath_rxdesc_init(sc, ds_tmp);
307
308                 asf_tailq_remove(&sc->sc_rxdesc_idle, ds_tmp, ds_list);
309                 asf_tailq_insert_tail(&sc->sc_rxdesc, ds_tmp, ds_list);
310         }
311 }
312
313 static void tgt_HTCSendCompleteHandler(HTC_ENDPOINT_ID Endpt, adf_nbuf_t buf, void *ServiceCtx)
314 {
315         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)ServiceCtx;
316
317         if (Endpt == RX_ENDPOINT_ID) {
318                 sc->sc_rx_stats.ast_rx_done++;
319                 ath_rx_complete(sc, buf);
320         }
321 }
322
323 static void ath_uapsd_processtriggers(struct ath_softc_tgt *sc)
324 {
325         struct ath_hal *ah = sc->sc_ah;
326         struct ath_rx_buf *bf = NULL;
327         struct ath_rx_desc *ds, *ds_head, *ds_tail, *ds_tmp;
328         a_int32_t retval;
329         a_uint32_t cnt = 0;
330         a_uint16_t frame_len = 0;
331         a_uint64_t tsf;
332
333 #define PA2DESC(_sc, _pa)                                               \
334         ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc +         \
335                              ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
336
337         tsf = ath_hal_gettsf64(ah);
338         bf = asf_tailq_first(&sc->sc_rxbuf);
339
340         ds = asf_tailq_first(&sc->sc_rxdesc);
341         ds_head = ds;
342
343         while(ds) {
344                 ++cnt;
345
346                 if (cnt == ath_numrxbufs - 1) {
347                         adf_os_print("VERY LONG PACKET!!!!!\n");
348                         ds_tail = ds;
349                         ds_tmp = ds_head;
350                         while (ds_tmp) {
351                                 struct ath_rx_desc *ds_rmv;
352                                 adf_nbuf_unmap(sc->sc_dev, ds_tmp->ds_dmap, ADF_OS_DMA_FROM_DEVICE);
353                                 ds_rmv = ds_tmp;
354                                 ds_tmp = asf_tailq_next(ds_tmp, ds_list);
355
356                                 if (ds_tmp == NULL) {
357                                         adf_os_print("ds_tmp is NULL\n");
358                                         adf_os_assert(0);
359                                 }
360
361                                 BUF_Pool_free_buf(sc->pool_handle, POOL_ID_WLAN_RX_BUF, ds_rmv->ds_nbuf);
362                                 ds_rmv->ds_nbuf = ADF_NBUF_NULL;
363
364                                 if (ath_rxdesc_init(sc, ds_rmv) == 0) {
365                                         asf_tailq_remove(&sc->sc_rxdesc, ds_rmv, ds_list);
366                                         asf_tailq_insert_tail(&sc->sc_rxdesc, ds_rmv, ds_list);
367                                 }
368                                 else {
369                                         asf_tailq_remove(&sc->sc_rxdesc, ds_rmv, ds_list);
370                                         asf_tailq_insert_tail(&sc->sc_rxdesc_idle, ds_rmv, ds_list);
371                                 }
372
373                                 if (ds_rmv == ds_tail) {
374                                         break;
375                                 }
376                         }
377                         break;
378                 }
379
380                 if (ds->ds_link == 0) {
381                         break;
382                 }
383
384                 if (bf->bf_status & ATH_BUFSTATUS_DONE) {
385                         continue;
386                 }
387
388                 retval = ath_hal_rxprocdescfast(ah, ds, ds->ds_daddr,
389                                                 PA2DESC(sc, ds->ds_link), &bf->bf_rx_status);
390                 if (HAL_EINPROGRESS == retval) {
391                         break;
392                 }
393
394                 if (adf_nbuf_len(ds->ds_nbuf) == 0) {
395                         adf_nbuf_put_tail(ds->ds_nbuf, bf->bf_rx_status.rs_datalen);
396                 }
397
398                 frame_len += bf->bf_rx_status.rs_datalen;
399
400                 if (bf->bf_rx_status.rs_more == 0) {
401                         adf_nbuf_queue_t nbuf_head;
402                         adf_nbuf_queue_init(&nbuf_head);
403
404                         cnt = 0;
405
406                         ds_tail = ds;
407                         ds = asf_tailq_next(ds, ds_list);
408
409                         ds_tmp = ds_head;
410                         ds_head = asf_tailq_next(ds_tail, ds_list);
411
412                         while (ds_tmp) {
413                                 struct ath_rx_desc *ds_rmv;
414
415                                 adf_nbuf_unmap(sc->sc_dev, ds_tmp->ds_dmap, ADF_OS_DMA_FROM_DEVICE);
416                                 adf_nbuf_queue_add(&nbuf_head, ds_tmp->ds_nbuf);
417                                 ds_tmp->ds_nbuf = ADF_NBUF_NULL;
418
419                                 ds_rmv = ds_tmp;
420                                 ds_tmp = asf_tailq_next(ds_tmp, ds_list);
421                                 if (ds_tmp == NULL) {
422                                         adf_os_assert(0);
423                                 }
424
425                                 if (ath_rxdesc_init(sc, ds_rmv) == 0) {
426                                         asf_tailq_remove(&sc->sc_rxdesc, ds_rmv, ds_list);
427                                         asf_tailq_insert_tail(&sc->sc_rxdesc, ds_rmv, ds_list);
428                                 }  else {
429                                         asf_tailq_remove(&sc->sc_rxdesc, ds_rmv, ds_list);
430                                         asf_tailq_insert_tail(&sc->sc_rxdesc_idle, ds_rmv, ds_list);
431                                 }
432
433                                 if (ds_rmv == ds_tail) {
434                                         break;
435                                 }
436                         }
437
438
439                         bf->bf_rx_status.rs_datalen = frame_len;
440                         frame_len = 0;
441
442                         bf->bf_skb = adf_nbuf_create_frm_frag(&nbuf_head);
443
444                         bf->bf_status |= ATH_BUFSTATUS_DONE;
445
446                         bf = (struct ath_rx_buf *)asf_tailq_next(bf, bf_list);
447                 }
448                 else {
449                         ds = asf_tailq_next(ds, ds_list);
450                 }
451         }
452
453 #undef PA2DESC
454 }
455
456 static a_int32_t ath_startrecv(struct ath_softc_tgt *sc)
457 {
458         struct ath_hal *ah = sc->sc_ah;
459         struct ath_rx_desc *ds;
460
461         sc->sc_rxbufsize = 1024+512+128;
462         sc->sc_rxlink = NULL;
463
464         sc->sc_rxdesc_held = NULL;
465
466         asf_tailq_foreach(ds, &sc->sc_rxdesc, ds_list) {
467                 a_int32_t error = ath_rxdesc_init(sc, ds);
468                 if (error != 0) {
469                         return error;
470                 }
471         }
472
473         ds = asf_tailq_first(&sc->sc_rxdesc);
474         ath_hal_putrxbuf(ah, ds->ds_daddr);
475
476         return 0;
477 }
478
479 static void ath_tgt_rx_tasklet(TQUEUE_ARG data)
480 {
481         struct ath_softc_tgt *sc  = (struct ath_softc_tgt *)data;
482         struct ath_rx_buf *bf = NULL;
483         struct ath_hal *ah = sc->sc_ah;
484         struct rx_frame_header *rxhdr;
485         struct ath_rx_status *rxstats;
486         adf_nbuf_t skb = ADF_NBUF_NULL;
487
488         do {
489                 bf = asf_tailq_first(&sc->sc_rxbuf);
490                 if (bf == NULL) {
491                         break;
492                 }
493
494                 if (!(bf->bf_status & ATH_BUFSTATUS_DONE)) {
495                         break;
496                 }
497
498                 skb = bf->bf_skb;
499                 if (skb == NULL) {
500                         continue;
501                 }
502
503                 asf_tailq_remove(&sc->sc_rxbuf, bf, bf_list);
504
505                 bf->bf_skb = NULL;
506
507                 rxhdr = (struct rx_frame_header *)adf_nbuf_push_head(skb,
508                                                      sizeof(struct rx_frame_header));
509                 rxstats = (struct ath_rx_status *)(&rxhdr->rx_stats[0]);
510                 adf_os_mem_copy(rxstats, &(bf->bf_rx_status),
511                                 sizeof(struct ath_rx_status));
512
513                 rxstats->rs_tstamp = ath_extend_tsf(sc, (u_int32_t)rxstats->rs_tstamp);
514
515                 HTC_SendMsg(sc->tgt_htc_handle, RX_ENDPOINT_ID, skb);
516                 sc->sc_rx_stats.ast_rx_send++;
517
518                 bf->bf_status &= ~ATH_BUFSTATUS_DONE;
519                 asf_tailq_insert_tail(&sc->sc_rxbuf, bf, bf_list);
520
521         } while(1);
522
523         sc->sc_imask |= HAL_INT_RX;
524         ath_hal_intrset(ah, sc->sc_imask);
525 }
526
527 /*******************/
528 /* Beacon Handling */
529 /*******************/
530
531 /*
532  * Setup the beacon frame for transmit.
533  * FIXME: Short Preamble.
534  */
535 static void ath_beacon_setup(struct ath_softc_tgt *sc,
536                              struct ath_tx_buf *bf,
537                              struct ath_vap_target *avp)
538 {
539         adf_nbuf_t skb = bf->bf_skb;
540         struct ath_hal *ah = sc->sc_ah;
541         struct ath_tx_desc *ds;
542         a_int32_t flags;
543         const HAL_RATE_TABLE *rt;
544         a_uint8_t rix, rate;
545         HAL_11N_RATE_SERIES series[4] = {{ 0 }};
546
547         flags = HAL_TXDESC_NOACK;
548
549         ds = bf->bf_desc;
550         ds->ds_link = 0;
551         ds->ds_data = bf->bf_dmamap_info.dma_segs[0].paddr;
552
553         rix = ath_get_minrateidx(sc, avp);
554         rt  = sc->sc_currates;
555         rate = rt->info[rix].rateCode;
556
557         ath_hal_setuptxdesc(ah, ds
558                             , adf_nbuf_len(skb) + IEEE80211_CRC_LEN
559                             , sizeof(struct ieee80211_frame)
560                             , HAL_PKT_TYPE_BEACON
561                             , MAX_RATE_POWER
562                             , rate, 1
563                             , HAL_TXKEYIX_INVALID
564                             , 0
565                             , flags
566                             , 0
567                             , 0
568                             , 0
569                             , 0
570                             , ATH_COMP_PROC_NO_COMP_NO_CCS);
571
572         ath_hal_filltxdesc(ah, ds
573                            , asf_roundup(adf_nbuf_len(skb), 4)
574                            , AH_TRUE
575                            , AH_TRUE
576                            , ds);
577
578         series[0].Tries = 1;
579         series[0].Rate = rate;
580         series[0].ChSel = sc->sc_ic.ic_tx_chainmask;
581         series[0].RateFlags = 0;
582         ath_hal_set11n_ratescenario(ah, ds, 0, 0, 0, series, 4, 0);
583 }
584
585 static void ath_tgt_send_beacon(struct ath_softc_tgt *sc, adf_nbuf_t bc_hdr,
586                                 adf_nbuf_t nbuf, HTC_ENDPOINT_ID EndPt)
587 {
588         struct ath_hal *ah = sc->sc_ah;
589         struct ath_tx_buf *bf;
590         a_uint8_t vap_index, *anbdata;
591         ath_beacon_hdr_t *bhdr;
592         struct ieee80211vap_target  *vap;
593         a_uint32_t anblen;
594         struct ieee80211_frame *wh;
595
596         if (!bc_hdr) {
597                 adf_nbuf_peek_header(nbuf, &anbdata, &anblen);
598                 bhdr = (ath_beacon_hdr_t *)anbdata;
599         } else {
600                 adf_os_print("found bc_hdr! 0x%x\n", bc_hdr);
601         }
602
603         vap_index = bhdr->vap_index;
604         adf_os_assert(vap_index < TARGET_VAP_MAX);
605         vap = &sc->sc_vap[vap_index].av_vap;
606
607         wh = (struct ieee80211_frame *)adf_nbuf_pull_head(nbuf,
608                                                   sizeof(ath_beacon_hdr_t));
609
610         bf = sc->sc_vap[vap_index].av_bcbuf;
611         adf_os_assert(bf);
612         bf->bf_endpt = EndPt;
613
614         if (bf->bf_skb) {
615                 adf_nbuf_unmap(sc->sc_dev, bf->bf_dmamap, ADF_OS_DMA_TO_DEVICE);
616                 adf_nbuf_push_head(bf->bf_skb, sizeof(ath_beacon_hdr_t));
617                 ath_free_tx_skb(sc->tgt_htc_handle, bf->bf_endpt, bf->bf_skb);
618         }
619
620         bf->bf_skb = nbuf;
621
622         adf_nbuf_map(sc->sc_dev, bf->bf_dmamap, nbuf, ADF_OS_DMA_TO_DEVICE);
623         adf_nbuf_dmamap_info(bf->bf_dmamap,&bf->bf_dmamap_info);
624
625         ath_beacon_setup(sc, bf, &sc->sc_vap[vap_index]);
626         ath_hal_stoptxdma(ah, sc->sc_bhalq);
627         ath_hal_puttxbuf(ah, sc->sc_bhalq, ATH_BUF_GET_DESC_PHY_ADDR(bf));
628         ath_hal_txstart(ah, sc->sc_bhalq);
629 }
630
631 /******/
632 /* TX */
633 /******/
634
635 static void ath_tx_stopdma(struct ath_softc_tgt *sc, struct ath_txq *txq)
636 {
637         struct ath_hal *ah = sc->sc_ah;
638
639         (void) ath_hal_stoptxdma(ah, txq->axq_qnum);
640 }
641
642 static void owltgt_txq_drain(struct ath_softc_tgt *sc, struct ath_txq *txq)
643 {
644         owltgt_tx_processq(sc, txq, OWL_TXQ_STOPPED);
645 }
646
647 static void ath_tx_draintxq(struct ath_softc_tgt *sc, struct ath_txq *txq)
648 {
649         owltgt_txq_drain(sc, txq);
650 }
651
652 static void ath_draintxq(struct ath_softc_tgt *sc, HAL_BOOL drain_softq)
653 {
654         struct ath_hal *ah = sc->sc_ah;
655         a_uint16_t i;
656         struct ath_txq *txq = NULL;
657         struct ath_atx_tid *tid = NULL;
658
659         ath_tx_status_clear(sc);
660         sc->sc_tx_draining = 1;
661
662         (void) ath_hal_stoptxdma(ah, sc->sc_bhalq);
663
664         for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
665                 if (ATH_TXQ_SETUP(sc, i))
666                         ath_tx_stopdma(sc, ATH_TXQ(sc, i));
667
668         for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
669                 if (ATH_TXQ_SETUP(sc, i)) {
670                         owltgt_tx_processq(sc, ATH_TXQ(sc,i), OWL_TXQ_STOPPED);
671
672                         txq = ATH_TXQ(sc,i);
673                         while (!asf_tailq_empty(&txq->axq_tidq)){
674                                 TAILQ_DEQ(&txq->axq_tidq, tid, tid_qelem);
675                                 if(tid == NULL)
676                                         break;
677                                 tid->sched = AH_FALSE;
678                                 ath_tgt_tid_drain(sc,tid);
679                         }
680                 }
681
682         sc->sc_tx_draining = 0;
683 }
684
685 static void ath_tgt_txq_setup(struct ath_softc_tgt *sc)
686 {
687         a_int32_t qnum;
688         struct ath_txq *txq;
689
690         sc->sc_txqsetup=0;
691
692         for (qnum=0;qnum<HAL_NUM_TX_QUEUES;qnum++) {
693                 txq= &sc->sc_txq[qnum];
694                 txq->axq_qnum = qnum;
695                 txq->axq_link = NULL;
696                 asf_tailq_init(&txq->axq_q);
697                 txq->axq_depth = 0;
698                 txq->axq_linkbuf = NULL;
699                 asf_tailq_init(&txq->axq_tidq);
700                 sc->sc_txqsetup |= 1<<qnum;
701         }
702
703         sc->sc_uapsdq  = &sc->sc_txq[UAPSDQ_NUM];
704         sc->sc_cabq    = &sc->sc_txq[CABQ_NUM];
705
706         sc->sc_ac2q[WME_AC_BE]  = &sc->sc_txq[0];
707         sc->sc_ac2q[WME_AC_BK]  = &sc->sc_txq[1];
708         sc->sc_ac2q[WME_AC_VI]  = &sc->sc_txq[2];
709         sc->sc_ac2q[WME_AC_VO]  = &sc->sc_txq[3];
710
711         return;
712 #undef N
713 }
714
715 static void tgt_HTCRecv_beaconhandler(HTC_ENDPOINT_ID EndPt, adf_nbuf_t hdr_buf,
716                                       adf_nbuf_t buf, void *ServiceCtx)
717 {
718         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)ServiceCtx;
719
720         ath_tgt_send_beacon(sc, hdr_buf, buf, EndPt);
721 }
722
723 static void tgt_HTCRecv_uapsdhandler(HTC_ENDPOINT_ID EndPt, adf_nbuf_t hdr_buf,
724                                      adf_nbuf_t buf, void *ServiceCtx)
725 {
726 }
727
728 static void tgt_HTCRecv_mgmthandler(HTC_ENDPOINT_ID EndPt, adf_nbuf_t hdr_buf,
729                                     adf_nbuf_t buf, void *ServiceCtx)
730 {
731         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)ServiceCtx;
732
733         ath_tgt_send_mgt(sc,hdr_buf,buf,EndPt);
734 }
735
736 static void tgt_HTCRecvMessageHandler(HTC_ENDPOINT_ID EndPt,
737                                       adf_nbuf_t hdr_buf, adf_nbuf_t buf,
738                                       void *ServiceCtx)
739 {
740         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)ServiceCtx;
741         struct ath_tx_buf *bf;
742         a_uint8_t *data;
743         a_uint32_t len;
744         ath_data_hdr_t *dh;
745         struct ath_node_target *an;
746         struct ath_atx_tid *tid;
747
748         if (!hdr_buf) {
749                 adf_nbuf_peek_header(buf, &data, &len);
750                 adf_nbuf_pull_head(buf, sizeof(ath_data_hdr_t));
751         } else {
752                 adf_nbuf_peek_header(hdr_buf, &data, &len);
753         }
754
755         adf_os_assert(len >= sizeof(ath_data_hdr_t));
756         dh = (ath_data_hdr_t *)data;
757
758         an = &sc->sc_sta[dh->ni_index];
759         tid = ATH_AN_2_TID(an, dh->tidno);
760
761         sc->sc_tx_stats.tx_tgt++;
762
763         bf = ath_tgt_tx_prepare(sc, buf, dh);
764         if (!bf) {
765                 ath_free_tx_skb(sc->tgt_htc_handle,EndPt,buf);
766                 return;
767         }
768
769         bf->bf_endpt = EndPt;
770         bf->bf_cookie = dh->cookie;
771
772         if (tid->flag & TID_AGGR_ENABLED)
773                 ath_tgt_handle_aggr(sc, bf);
774         else
775                 ath_tgt_handle_normal(sc, bf);
776 }
777
778 static void tgt_HTCRecv_cabhandler(HTC_ENDPOINT_ID EndPt, adf_nbuf_t hdr_buf,
779                                    adf_nbuf_t buf, void *ServiceCtx)
780 {
781         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)ServiceCtx;
782         struct ath_hal *ah = sc->sc_ah;
783         a_uint64_t tsf;
784         a_uint32_t tmp;
785
786 #ifdef ATH_ENABLE_CABQ
787         tsf = ath_hal_gettsf64(ah);
788         tmp = tsf - sc->sc_swba_tsf;
789
790         if ( tmp > ATH_CABQ_HANDLING_THRESHOLD ) {
791                 HTC_ReturnBuffers(sc->tgt_htc_handle, EndPt, buf);
792                 return;
793         }
794
795         tgt_HTCRecvMessageHandler(EndPt, hdr_buf, buf, ServiceCtx);
796 #endif
797 }
798
799 /***********************/
800 /* Descriptor Handling */
801 /***********************/
802
803 static a_int32_t ath_descdma_setup(struct ath_softc_tgt *sc,
804                                    struct ath_descdma *dd, ath_bufhead *head,
805                                    const char *name, a_int32_t nbuf, a_int32_t ndesc,
806                                    a_uint32_t bfSize, a_uint32_t descSize)
807 {
808 #define DS2PHYS(_dd, _ds)                                               \
809         ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
810
811         struct ath_desc *ds;
812         struct ath_buf *bf;
813         a_int32_t i, bsize, error;
814         a_uint8_t *bf_addr;
815         a_uint8_t *ds_addr;
816
817         dd->dd_name = name;
818         dd->dd_desc_len = descSize * nbuf * ndesc;
819
820         dd->dd_desc = adf_os_dmamem_alloc(sc->sc_dev,
821                                   dd->dd_desc_len, 1, &dd->dd_desc_dmamap);
822         dd->dd_desc_paddr = adf_os_dmamem_map2addr(dd->dd_desc_dmamap);
823         if (dd->dd_desc == NULL) {
824                 error = -ENOMEM;
825                 goto fail;
826         }
827         ds = dd->dd_desc;
828
829         bsize = bfSize * nbuf;
830         bf = adf_os_mem_alloc(bsize);
831         if (bf == NULL) {
832                 error = -ENOMEM;
833                 goto fail2;
834         }
835         adf_os_mem_set(bf, 0, bsize);
836         dd->dd_bufptr = bf;
837
838         bf_addr = (a_uint8_t *)bf;
839         ds_addr = (a_uint8_t *)ds;
840
841         asf_tailq_init(head);
842
843         for (i = 0; i < nbuf; i++) {
844                 a_int32_t j;
845
846                 if (adf_nbuf_dmamap_create( sc->sc_dev, &bf->bf_dmamap) != A_STATUS_OK) {
847                         goto fail2;
848                 }
849
850                 bf->bf_desc = bf->bf_descarr = bf->bf_lastds = ds;
851                 for (j = 0; j < ndesc; j++)
852                         ATH_BUF_SET_DESC_PHY_ADDR_WITH_IDX(bf, j, (ds_addr + (j*descSize)));
853
854                 ATH_BUF_SET_DESC_PHY_ADDR(bf, ATH_BUF_GET_DESC_PHY_ADDR_WITH_IDX(bf, 0));
855
856                 adf_nbuf_queue_init(&bf->bf_skbhead);
857                 asf_tailq_insert_tail(head, bf, bf_list);
858
859                 bf_addr += bfSize;
860                 ds_addr += (ndesc * descSize);
861                 bf = (struct ath_buf *)bf_addr;
862                 ds = (struct ath_desc *)ds_addr;
863         }
864
865         return 0;
866 fail2:
867         adf_os_dmamem_free(sc->sc_dev, dd->dd_desc_len,
868                            1, dd->dd_desc, dd->dd_desc_dmamap);
869 fail:
870         adf_os_mem_set(dd, 0, sizeof(*dd));
871         adf_os_assert(0);
872         return error;
873
874 #undef DS2PHYS
875 }
876
877 static void ath_descdma_cleanup(struct ath_softc_tgt *sc,
878                                 struct ath_descdma *dd,
879                                 ath_bufhead *head, a_int32_t dir)
880 {
881         struct ath_buf *bf;
882         struct ieee80211_node_target *ni;
883
884         asf_tailq_foreach(bf, head, bf_list) {
885                 if (adf_nbuf_queue_len(&bf->bf_skbhead) != 0) {
886                         adf_nbuf_unmap(sc->sc_dev, bf->bf_dmamap, dir);
887                         while(adf_nbuf_queue_len(&bf->bf_skbhead) != 0) {
888                                 ath_free_rx_skb(sc,
889                                         adf_nbuf_queue_remove(&bf->bf_skbhead));
890                         }
891                         bf->bf_skb = NULL;
892                 } else if (bf->bf_skb != NULL) {
893                         adf_nbuf_unmap(sc->sc_dev,bf->bf_dmamap, dir);
894                         ath_free_rx_skb(sc, bf->bf_skb);
895                         bf->bf_skb = NULL;
896                 }
897
898                 adf_nbuf_dmamap_destroy(sc->sc_dev, bf->bf_dmamap);
899
900                 ni = bf->bf_node;
901                 bf->bf_node = NULL;
902         }
903
904         adf_os_dmamem_free(sc->sc_dev, dd->dd_desc_len,
905                            1, dd->dd_desc, dd->dd_desc_dmamap);
906
907         asf_tailq_init(head);
908         adf_os_mem_free(dd->dd_bufptr);
909         adf_os_mem_set(dd, 0, sizeof(*dd));
910 }
911
912 static a_int32_t ath_desc_alloc(struct ath_softc_tgt *sc)
913 {
914 #define DS2PHYS(_dd, _ds)                                               \
915         ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
916
917         a_int32_t error;
918         struct ath_tx_buf *bf;
919
920         if(ath_numrxbufs == -1)
921                 ath_numrxbufs = ATH_RXBUF;
922
923         if (ath_numrxdescs == -1)
924                 ath_numrxdescs = ATH_RXDESC;
925
926         error = ath_descdma_setup(sc, &sc->sc_rxdma, (ath_bufhead *)&sc->sc_rxbuf,
927                                   "rx", ath_numrxdescs, 1,
928                                   sizeof(struct ath_rx_buf),
929                                   sizeof(struct ath_rx_desc));
930         if (error != 0)
931                 return error;
932
933         a_uint32_t i;
934         struct ath_descdma *dd = &sc->sc_rxdma;
935         struct ath_rx_desc *ds = (struct ath_rx_desc *)dd->dd_desc;
936         struct ath_rx_desc *ds_prev = NULL;
937
938         asf_tailq_init(&sc->sc_rxdesc);
939         asf_tailq_init(&sc->sc_rxdesc_idle);
940
941         for (i = 0; i < ath_numrxdescs; i++, ds++) {
942
943                 if (ds->ds_nbuf != ADF_NBUF_NULL) {
944                         ds->ds_nbuf = ADF_NBUF_NULL;
945                 }
946
947                 if (adf_nbuf_dmamap_create(sc->sc_dev, &ds->ds_dmap) != A_STATUS_OK) {
948                         adf_os_assert(0);
949                 }
950
951                 ds->ds_daddr = DS2PHYS(&sc->sc_rxdma, ds);
952
953                 if (ds_prev) {
954                         ds_prev->ds_link = ds->ds_daddr;
955                 }
956
957                 ds->ds_link = 0;
958                 ds_prev = ds;
959
960                 asf_tailq_insert_tail(&sc->sc_rxdesc, ds, ds_list);
961         }
962
963         error = ath_descdma_setup(sc, &sc->sc_txdma, (ath_bufhead *)&sc->sc_txbuf,
964                                   "tx", ATH_TXBUF + 1, ATH_TXDESC,
965                                   sizeof(struct ath_tx_buf),
966                                   sizeof(struct ath_tx_desc));
967         if (error != 0) {
968                 ath_descdma_cleanup(sc, &sc->sc_rxdma, (ath_bufhead *)&sc->sc_rxbuf,
969                                     ADF_OS_DMA_FROM_DEVICE);
970                 return error;
971         }
972
973         error = ath_descdma_setup(sc, &sc->sc_bdma, (ath_bufhead *)&sc->sc_bbuf,
974                                   "beacon", ATH_BCBUF, 1,
975                                   sizeof(struct ath_tx_buf),
976                                   sizeof(struct ath_tx_desc));
977         if (error != 0) {
978                 ath_descdma_cleanup(sc, &sc->sc_txdma, (ath_bufhead *)&sc->sc_txbuf,
979                                     ADF_OS_DMA_TO_DEVICE);
980                 ath_descdma_cleanup(sc, &sc->sc_rxdma, (ath_bufhead *)&sc->sc_rxbuf,
981                                     ADF_OS_DMA_FROM_DEVICE);
982                 return error;
983         }
984
985         bf = asf_tailq_first(&sc->sc_txbuf);
986         bf->bf_isaggr = bf->bf_isretried = bf->bf_retries = 0;
987         asf_tailq_remove(&sc->sc_txbuf, bf, bf_list);
988
989         sc->sc_txbuf_held = bf;
990
991         return 0;
992
993 #undef DS2PHYS
994 }
995
996 static void ath_desc_free(struct ath_softc_tgt *sc)
997 {
998         asf_tailq_insert_tail(&sc->sc_txbuf, sc->sc_txbuf_held, bf_list);
999
1000         sc->sc_txbuf_held = NULL;
1001
1002         if (sc->sc_txdma.dd_desc_len != 0)
1003                 ath_descdma_cleanup(sc, &sc->sc_txdma, (ath_bufhead *)&sc->sc_txbuf,
1004                                     ADF_OS_DMA_TO_DEVICE);
1005         if (sc->sc_rxdma.dd_desc_len != 0)
1006                 ath_descdma_cleanup(sc, &sc->sc_rxdma, (ath_bufhead *)&sc->sc_rxbuf,
1007                                     ADF_OS_DMA_FROM_DEVICE);
1008 }
1009
1010 /**********************/
1011 /* Interrupt Handling */
1012 /**********************/
1013
1014 adf_os_irq_resp_t ath_intr(adf_drv_handle_t hdl)
1015 {
1016         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)hdl;
1017         struct ath_hal *ah = sc->sc_ah;
1018         HAL_INT status;
1019
1020         if (sc->sc_invalid)
1021                 return ADF_OS_IRQ_NONE;
1022
1023         if (!ath_hal_intrpend(ah))
1024                 return ADF_OS_IRQ_NONE;
1025
1026         ath_hal_getisr(ah, &status);
1027
1028         status &= sc->sc_imask;
1029
1030         if (status & HAL_INT_FATAL) {
1031                 ath_hal_intrset(ah, 0);
1032                 ATH_SCHEDULE_TQUEUE(sc->sc_dev, &sc->sc_fataltq);
1033         } else {
1034                 if (status & HAL_INT_SWBA) {
1035                         WMI_SWBA_EVENT swbaEvt;
1036                         struct ath_txq *txq = ATH_TXQ(sc, 8);
1037
1038                         swbaEvt.tsf = ath_hal_gettsf64(ah);
1039                         swbaEvt.beaconPendingCount = ath_hal_numtxpending(ah, sc->sc_bhalq);
1040                         sc->sc_swba_tsf = ath_hal_gettsf64(ah);
1041
1042                         wmi_event(sc->tgt_wmi_handle,
1043                                   WMI_SWBA_EVENTID,
1044                                   &swbaEvt,
1045                                   sizeof(WMI_SWBA_EVENT));
1046
1047                         ath_tx_draintxq(sc, txq);
1048                 }
1049
1050                 if (status & HAL_INT_RXORN)
1051                         sc->sc_int_stats.ast_rxorn++;
1052
1053                 if (status & HAL_INT_RXEOL)
1054                         sc->sc_int_stats.ast_rxeol++;
1055
1056                 if (status & (HAL_INT_RX | HAL_INT_RXEOL | HAL_INT_RXORN)) {
1057                         if (status & HAL_INT_RX)
1058                                 sc->sc_int_stats.ast_rx++;
1059
1060                         ath_uapsd_processtriggers(sc);
1061
1062                         sc->sc_imask &= ~HAL_INT_RX;
1063                         ath_hal_intrset(ah, sc->sc_imask);
1064
1065                         ATH_SCHEDULE_TQUEUE(sc->sc_dev, &sc->sc_rxtq);
1066                 }
1067
1068                 if (status & HAL_INT_TXURN) {
1069                         sc->sc_int_stats.ast_txurn++;
1070                         ath_hal_updatetxtriglevel(ah, AH_TRUE);
1071                 }
1072
1073                 ATH_SCHEDULE_TQUEUE(sc->sc_dev, &sc->sc_txtq);
1074
1075                 if (status & HAL_INT_BMISS) {
1076                         ATH_SCHEDULE_TQUEUE(sc->sc_dev, &sc->sc_bmisstq);
1077                 }
1078
1079                 if (status & HAL_INT_GTT)
1080                         sc->sc_int_stats.ast_txto++;
1081
1082                 if (status & HAL_INT_CST)
1083                         sc->sc_int_stats.ast_cst++;
1084         }
1085
1086         return ADF_OS_IRQ_HANDLED;
1087 }
1088
1089 static void ath_fatal_tasklet(TQUEUE_ARG data )
1090 {
1091         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)data;
1092
1093         wmi_event(sc->tgt_wmi_handle, WMI_FATAL_EVENTID, NULL, 0);
1094 }
1095
1096 static void ath_bmiss_tasklet(TQUEUE_ARG data)
1097 {
1098         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)data;
1099
1100         wmi_event(sc->tgt_wmi_handle, WMI_BMISS_EVENTID, NULL, 0);
1101 }
1102
1103 /****************/
1104 /* WMI Commands */
1105 /****************/
1106
1107 static void ath_enable_intr_tgt(void *Context, A_UINT16 Command,
1108                                 A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1109 {
1110         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1111         struct ath_hal *ah = sc->sc_ah;
1112         a_uint32_t intr;
1113
1114         if (data)
1115                 intr = (*(a_uint32_t *)data);
1116
1117         intr = adf_os_ntohl(intr);
1118
1119         if (intr & HAL_INT_SWBA) {
1120                 sc->sc_imask |= HAL_INT_SWBA;
1121         } else {
1122                 sc->sc_imask &= ~HAL_INT_SWBA;
1123         }
1124
1125         if (intr & HAL_INT_BMISS) {
1126                 sc->sc_imask |= HAL_INT_BMISS;
1127         }
1128
1129         ath_hal_intrset(ah, sc->sc_imask);
1130         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo,NULL, 0);
1131 }
1132
1133 static void ath_init_tgt(void *Context, A_UINT16 Command,
1134                          A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1135 {
1136         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1137         struct ath_hal *ah = sc->sc_ah;
1138
1139         sc->sc_imask = HAL_INT_RX | HAL_INT_TX
1140                 | HAL_INT_RXEOL | HAL_INT_RXORN
1141                 | HAL_INT_FATAL | HAL_INT_GLOBAL;
1142
1143         sc->sc_imask |= HAL_INT_GTT;
1144
1145         if (ath_hal_htsupported(ah))
1146                 sc->sc_imask |= HAL_INT_CST;
1147
1148         adf_os_setup_intr(sc->sc_dev, ath_intr);
1149         ath_hal_intrset(ah, sc->sc_imask);
1150
1151         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1152 }
1153
1154 static void ath_int_stats_tgt(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1155                               A_UINT8 *data, a_int32_t datalen)
1156 {
1157         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1158
1159         struct fusion_stats {
1160                 a_uint32_t ast_rx;
1161                 a_uint32_t ast_rxorn;
1162                 a_uint32_t ast_rxeol;
1163                 a_uint32_t ast_txurn;
1164                 a_uint32_t ast_txto;
1165                 a_uint32_t ast_cst;
1166         };
1167
1168         struct fusion_stats stats;
1169
1170         stats.ast_rx = sc->sc_int_stats.ast_rx;
1171         stats.ast_rxorn = sc->sc_int_stats.ast_rxorn;
1172         stats.ast_rxeol = sc->sc_int_stats.ast_rxeol;
1173         stats.ast_txurn = sc->sc_int_stats.ast_txurn;
1174         stats.ast_txto = sc->sc_int_stats.ast_txto;
1175         stats.ast_cst = sc->sc_int_stats.ast_cst;
1176
1177         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, &stats, sizeof(stats));
1178 }
1179
1180 static void ath_tx_stats_tgt(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1181                              A_UINT8 *data, a_int32_t datalen)
1182 {
1183         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1184
1185         struct fusion_stats {
1186                 a_uint32_t   ast_tx_xretries;
1187                 a_uint32_t   ast_tx_fifoerr;
1188                 a_uint32_t   ast_tx_filtered;
1189                 a_uint32_t   ast_tx_timer_exp;
1190                 a_uint32_t   ast_tx_shortretry;
1191                 a_uint32_t   ast_tx_longretry;
1192
1193                 a_uint32_t   tx_qnull;
1194                 a_uint32_t   tx_noskbs;
1195                 a_uint32_t   tx_nobufs;
1196         };
1197
1198         struct fusion_stats stats;
1199
1200         stats.ast_tx_xretries = sc->sc_tx_stats.ast_tx_xretries;
1201         stats.ast_tx_fifoerr = sc->sc_tx_stats.ast_tx_fifoerr;
1202         stats.ast_tx_filtered = sc->sc_tx_stats.ast_tx_filtered;
1203         stats.ast_tx_timer_exp = sc->sc_tx_stats.ast_tx_timer_exp;
1204         stats.ast_tx_shortretry = sc->sc_tx_stats.ast_tx_shortretry;
1205         stats.ast_tx_longretry = sc->sc_tx_stats.ast_tx_longretry;
1206         stats.tx_qnull = sc->sc_tx_stats.tx_qnull;
1207         stats.tx_noskbs = sc->sc_tx_stats.tx_noskbs;
1208         stats.tx_nobufs = sc->sc_tx_stats.tx_nobufs;
1209
1210         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, &stats, sizeof(stats));
1211 }
1212
1213 static void ath_rx_stats_tgt(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1214                              A_UINT8 *data, a_int32_t datalen)
1215 {
1216         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1217
1218         struct fusion_stats {
1219                 a_uint32_t   ast_rx_nobuf;
1220                 a_uint32_t   ast_rx_send;
1221                 a_uint32_t   ast_rx_done;
1222         };
1223
1224         struct fusion_stats stats;
1225
1226         stats.ast_rx_nobuf = sc->sc_rx_stats.ast_rx_nobuf;
1227         stats.ast_rx_send = sc->sc_rx_stats.ast_rx_send;
1228         stats.ast_rx_done = sc->sc_rx_stats.ast_rx_done;
1229
1230         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, &stats, sizeof(stats));
1231 }
1232
1233 static void ath_get_tgt_version(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1234                                 A_UINT8 *data, a_int32_t datalen)
1235 {
1236         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1237         struct wmi_fw_version ver;
1238
1239         ver.major = ATH_VERSION_MAJOR;
1240         ver.minor = ATH_VERSION_MINOR;
1241
1242         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, &ver, sizeof(ver));
1243 }
1244
1245 static void ath_enable_aggr_tgt(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1246                                 A_UINT8 *data, a_int32_t datalen)
1247 {
1248         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1249         struct ath_aggr_info *aggr = (struct ath_aggr_info *)data;
1250         a_uint8_t nodeindex = aggr->nodeindex;
1251         a_uint8_t tidno = aggr->tidno;
1252         struct ath_node_target *an = NULL ;
1253         struct ath_atx_tid  *tid = NULL;
1254
1255         if (nodeindex >= TARGET_NODE_MAX) {
1256                 goto done;
1257         }
1258
1259         an = &sc->sc_sta[nodeindex];
1260         if (!an->an_valid) {
1261                 goto done;
1262         }
1263
1264         if (tidno >= WME_NUM_TID) {
1265                 adf_os_print("[%s] enable_aggr with invalid tid %d(node = %d)\n",
1266                              __FUNCTION__, tidno, nodeindex);
1267                 goto done;
1268         }
1269
1270         tid = ATH_AN_2_TID(an, tidno);
1271
1272         if (aggr->aggr_enable) {
1273                 tid->flag |= TID_AGGR_ENABLED;
1274         } else if ( tid->flag & TID_AGGR_ENABLED ) {
1275                 tid->flag &= ~TID_AGGR_ENABLED;
1276                 ath_tgt_tx_cleanup(sc, an, tid, 1);
1277         }
1278 done:
1279         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1280 }
1281
1282 static void ath_ic_update_tgt(void *Context,A_UINT16 Command, A_UINT16 SeqNo,
1283                               A_UINT8 *data, a_int32_t datalen)
1284 {
1285         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1286         struct ieee80211com_target *ic = (struct ieee80211com_target * )data;
1287         struct ieee80211com_target *ictgt = &sc->sc_ic ;
1288
1289         adf_os_mem_copy(ictgt, ic, sizeof(struct  ieee80211com_target));
1290
1291         ictgt->ic_ampdu_limit         = adf_os_ntohl(ic->ic_ampdu_limit);
1292
1293         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1294 }
1295
1296 static void ath_vap_create_tgt(void *Context, A_UINT16 Command, A_UINT16 SeqNo,
1297                                A_UINT8 *data, a_int32_t datalen)
1298 {
1299         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1300         struct ieee80211vap_target *vap;
1301         a_uint8_t vap_index;
1302
1303         vap = (struct ieee80211vap_target *)data;
1304
1305         vap->iv_rtsthreshold    = adf_os_ntohs(vap->iv_rtsthreshold);
1306         vap->iv_opmode          = adf_os_ntohl(vap->iv_opmode);
1307
1308         vap_index = vap->iv_vapindex;
1309
1310         adf_os_assert(sc->sc_vap[vap_index].av_valid == 0);
1311
1312         adf_os_mem_copy(&(sc->sc_vap[vap_index].av_vap), vap,
1313                         VAP_TARGET_SIZE);
1314
1315         sc->sc_vap[vap_index].av_bcbuf = asf_tailq_first(&(sc->sc_bbuf));
1316         sc->sc_vap[vap_index].av_valid = 1;
1317
1318         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1319 }
1320
1321 static void ath_node_create_tgt(void *Context, A_UINT16 Command,
1322                                 A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1323 {
1324         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1325         struct ieee80211_node_target *node;
1326         a_uint8_t vap_index;
1327         a_uint8_t node_index;
1328
1329         node = (struct ieee80211_node_target *)data;
1330
1331         node_index = node->ni_nodeindex;
1332
1333         node->ni_htcap = adf_os_ntohs(node->ni_htcap);
1334         node->ni_flags = adf_os_ntohs(node->ni_flags);
1335         node->ni_maxampdu = adf_os_ntohs(node->ni_maxampdu);
1336
1337         adf_os_mem_copy(&(sc->sc_sta[node_index].ni), node,
1338                         NODE_TARGET_SIZE);
1339
1340         vap_index = sc->sc_sta[node_index].ni.ni_vapindex;
1341         sc->sc_sta[node_index].ni.ni_vap = &(sc->sc_vap[vap_index].av_vap);
1342         if(sc->sc_sta[node_index].ni.ni_is_vapnode == 1)
1343                 sc->sc_vap[vap_index].av_vap.iv_nodeindex = node_index;
1344
1345         sc->sc_sta[node_index].an_valid = 1;
1346         sc->sc_sta[node_index].ni.ni_txseqmgmt = 0;
1347         sc->sc_sta[node_index].ni.ni_iv16 = 0;
1348         sc->sc_sta[node_index].ni.ni_iv32 = 0;
1349
1350         owl_tgt_node_init(&sc->sc_sta[node_index]);
1351
1352         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1353 }
1354
1355 static void ath_node_cleanup_tgt(void *Context, A_UINT16 Command,
1356                                  A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1357 {
1358         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1359         a_uint8_t node_index;
1360         a_uint8_t *nodedata;
1361
1362         nodedata = (a_uint8_t *)data;
1363         node_index = *nodedata;
1364         sc->sc_sta[node_index].an_valid = 0;
1365
1366         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1367 }
1368
1369 static void ath_node_update_tgt(void *Context, A_UINT16 Command,
1370                                 A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1371 {
1372         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1373         struct ieee80211_node_target *node;
1374         a_uint8_t vap_index;
1375         a_uint8_t node_index;
1376
1377         node = (struct ieee80211_node_target *)data;
1378
1379         node_index = node->ni_nodeindex;
1380
1381         node->ni_htcap = adf_os_ntohs(node->ni_htcap);
1382         node->ni_flags = adf_os_ntohs(node->ni_flags);
1383         node->ni_maxampdu = adf_os_ntohs(node->ni_maxampdu);
1384
1385         adf_os_mem_copy(&(sc->sc_sta[node_index].ni), node,
1386                         NODE_TARGET_SIZE);
1387
1388         vap_index = sc->sc_sta[node_index].ni.ni_vapindex;
1389         sc->sc_sta[node_index].ni.ni_vap = &(sc->sc_vap[vap_index].av_vap);
1390
1391         sc->sc_sta[node_index].ni.ni_txseqmgmt = 0;
1392         sc->sc_sta[node_index].ni.ni_iv16 = 0;
1393         sc->sc_sta[node_index].ni.ni_iv32 = 0;
1394
1395         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1396 }
1397
1398 static void ath_hal_reg_read_tgt(void *Context, A_UINT16 Command,
1399                                  A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1400 {
1401         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1402         struct ath_hal *ah = sc->sc_ah;
1403         a_uint32_t addr;
1404         a_uint32_t val[32];
1405         int i;
1406
1407         for (i = 0; i < datalen; i += sizeof(a_int32_t)) {
1408                 addr = *(a_uint32_t *)(data + i);
1409                 addr = adf_os_ntohl(addr);
1410
1411                 if ((addr & 0xffffe000) == 0x2000) {
1412                         /* SEEPROM */
1413                         ath_hal_reg_read_target(ah, addr);
1414                         if (!ath_hal_wait(ah, 0x407c, 0x00030000, 0)) {
1415                                 adf_os_print("SEEPROM Read fail: 0x%08x\n", addr);
1416                         }
1417                         val[i/sizeof(a_int32_t)] = (ath_hal_reg_read_target(ah, 0x407c) & 0x0000ffff);
1418                 } else if (addr > 0xffff) {
1419                         val[i/sizeof(a_int32_t)] = *(a_uint32_t *)addr;
1420                 } else
1421                         val[i/sizeof(a_int32_t)] = ath_hal_reg_read_target(ah, addr);
1422
1423                 val[i/sizeof(a_int32_t)] = adf_os_ntohl(val[i/sizeof(a_int32_t)]);
1424         }
1425
1426         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, &val[0], datalen);
1427 }
1428
1429 static void ath_hal_reg_write_tgt(void *Context, A_UINT16 Command,
1430                                   A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1431 {
1432         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1433         struct ath_hal *ah = sc->sc_ah;
1434         int i;
1435         struct registerWrite {
1436                 a_uint32_t reg;
1437                 a_uint32_t val;
1438         }*t;
1439
1440         for (i = 0; i < datalen; i += sizeof(struct registerWrite)) {
1441                 t = (struct registerWrite *)(data+i);
1442
1443                 if( t->reg > 0xffff ) {
1444                         a_uint32_t *pReg = (a_uint32_t *)t->reg;
1445
1446                         *pReg = t->val;
1447
1448 #if defined(PROJECT_K2)
1449                         if( t->reg == 0x50040 ) {
1450                                 static uint8_t flg=0;
1451
1452                                 if( flg == 0 ) {
1453                                         A_CLOCK_INIT(117);
1454                                         A_UART_HWINIT(117*1000*1000, 19200);
1455                                         flg = 1;
1456                                 }
1457                         }
1458 #endif
1459                 } else {
1460 #if defined(PROJECT_K2)
1461                         if( t->reg == 0x7014 ) {
1462                                 static uint8_t resetPLL = 0;
1463                                 a_uint32_t *pReg;
1464
1465                                 if( resetPLL == 0 ) {
1466                                         t->reg = 0x50044;
1467                                         pReg = (a_uint32_t *)t->reg;
1468                                         *pReg = 0;
1469                                         ath_hal_reg_write_target(ah, 0x786c,
1470                                                  ath_hal_reg_read_target(ah,0x786c) | 0x6000000);
1471                                         ath_hal_reg_write_target(ah, 0x786c,
1472                                                  ath_hal_reg_read_target(ah,0x786c) & (~0x6000000));
1473                                         *pReg = 0x20;
1474                                         resetPLL = 1;
1475                                 }
1476                                 t->reg = 0x7014;
1477                         }
1478 #elif defined(PROJECT_MAGPIE) && !defined (FPGA)
1479                         if( t->reg == 0x7014 ){
1480                                 static uint8_t resetPLL = 0;
1481
1482                                 if( resetPLL == 0 ) {
1483                                         ath_hal_reg_write_target(ah, 0x7890,
1484                                                  ath_hal_reg_read_target(ah,0x7890) | 0x1800000);
1485                                         ath_hal_reg_write_target(ah, 0x7890,
1486                                                  ath_hal_reg_read_target(ah,0x7890) & (~0x1800000));
1487                                         resetPLL = 1;
1488                                 }
1489                         }
1490 #endif
1491                         ath_hal_reg_write_target(ah,t->reg,t->val);
1492                 }
1493         }
1494
1495         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1496 }
1497
1498 static void ath_vap_delete_tgt(void *Context, A_UINT16 Command,
1499                                A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1500 {
1501         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1502         a_uint8_t vap_index;
1503
1504         vap_index = *(a_uint8_t *)data;
1505
1506         sc->sc_vap[vap_index].av_valid = 0;
1507         sc->sc_vap[vap_index].av_bcbuf = NULL;
1508         ath_node_vdelete_tgt(sc, vap_index);
1509         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1510 }
1511
1512 static void ath_disable_intr_tgt(void *Context, A_UINT16 Command,
1513                                  A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1514 {
1515         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1516         struct ath_hal *ah = sc->sc_ah;
1517
1518         ath_hal_intrset(ah, 0);
1519         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo,NULL, 0);
1520 }
1521
1522 static void ath_flushrecv_tgt(void *Context, A_UINT16 Command,
1523                               A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1524 {
1525         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1526         struct ath_rx_buf *bf;
1527
1528         asf_tailq_foreach(bf, &sc->sc_rxbuf, bf_list)
1529                 if (bf->bf_skb != NULL) {
1530                         adf_nbuf_unmap(sc->sc_dev, bf->bf_dmamap,
1531                                        ADF_OS_DMA_FROM_DEVICE);
1532                         ath_free_rx_skb(sc, adf_nbuf_queue_remove(&bf->bf_skbhead));
1533                         bf->bf_skb = NULL;
1534                 }
1535
1536         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1537 }
1538
1539 static void ath_tx_draintxq_tgt(void *Context, A_UINT16 Command, A_UINT16 SeqNo,
1540                                 A_UINT8 *data, a_int32_t datalen)
1541 {
1542         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1543         a_uint32_t q = *(a_uint32_t *)data;
1544         struct ath_txq *txq = NULL;
1545
1546         q = adf_os_ntohl(q);
1547         txq = ATH_TXQ(sc, q);
1548
1549         ath_tx_draintxq(sc, txq);
1550         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1551 }
1552
1553 static void ath_draintxq_tgt(void *Context, A_UINT16 Command,
1554                              A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1555 {
1556         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1557         HAL_BOOL b = (HAL_BOOL) *(a_int32_t *)data;
1558
1559         ath_draintxq(Context, b);
1560         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1561 }
1562
1563 static void ath_aborttx_dma_tgt(void *Context, A_UINT16 Command,
1564                                 A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1565 {
1566         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1567
1568         ath_hal_aborttxdma(sc->sc_ah);
1569         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1570 }
1571
1572 static void ath_aborttxq_tgt(void *Context, A_UINT16 Command,
1573                              A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1574 {
1575
1576         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1577         a_uint16_t i;
1578
1579         for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
1580                 if (ATH_TXQ_SETUP(sc, i))
1581                         ath_tx_draintxq(sc, ATH_TXQ(sc,i));
1582         }
1583
1584         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1585 }
1586
1587 static void ath_stop_tx_dma_tgt(void *Context, A_UINT16 Command,
1588                                 A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1589 {
1590         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1591         struct ath_hal *ah = sc->sc_ah;
1592         a_uint32_t q;
1593
1594         if (data)
1595                 q = *(a_uint32_t *)data;
1596
1597         q = adf_os_ntohl(q);
1598         ath_hal_stoptxdma(ah, q);
1599         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1600 }
1601
1602 static void ath_startrecv_tgt(void *Context, A_UINT16 Command,
1603                               A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1604 {
1605
1606         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1607
1608         ath_startrecv(sc);
1609         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1610 }
1611
1612 static void ath_stoprecv_tgt(void *Context, A_UINT16 Command,
1613                              A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1614 {
1615         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1616         struct ath_hal *ah = sc->sc_ah;
1617
1618         ath_hal_stoppcurecv(ah);
1619         ath_hal_setrxfilter(ah, 0);
1620         ath_hal_stopdmarecv(ah);
1621
1622         sc->sc_rxlink = NULL;
1623         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1624 }
1625
1626 static void ath_setcurmode_tgt(void *Context, A_UINT16 Command,
1627                                A_UINT16 SeqNo, A_UINT8 *data, a_int32_t datalen)
1628 {
1629         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1630         a_uint16_t mode;
1631
1632         mode= *((a_uint16_t *)data);
1633         mode = adf_os_ntohs(mode);
1634
1635         ath_setcurmode(sc, mode);
1636
1637         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1638 }
1639
1640 static void ath_detach_tgt(void *Context, A_UINT16 Command, A_UINT16 SeqNo,
1641                                  A_UINT8 *data, a_int32_t datalen)
1642 {
1643         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1644         struct ath_hal *ah = sc->sc_ah;
1645
1646         ath_desc_free(sc);
1647         ath_hal_detach(ah);
1648         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1649         adf_os_mem_free(sc);
1650 }
1651
1652 static void handle_echo_command(void *pContext, A_UINT16 Command,
1653                                 A_UINT16 SeqNo, A_UINT8 *buffer, a_int32_t Length)
1654 {
1655         wmi_cmd_rsp(pContext, WMI_ECHO_CMDID, SeqNo, buffer, Length);
1656 }
1657
1658 static void handle_rc_state_change_cmd(void *Context, A_UINT16 Command,
1659                                        A_UINT16 SeqNo, A_UINT8 *buffer, a_int32_t Length)
1660
1661 {
1662         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1663         struct wmi_rc_state_change_cmd *wmi_data = (struct wmi_rc_state_change_cmd *)buffer;
1664
1665         a_uint32_t capflag = adf_os_ntohl(wmi_data->capflag);
1666
1667         ath_rate_newstate(sc, &sc->sc_vap[wmi_data->vap_index].av_vap,
1668                           wmi_data->vap_state,
1669                           capflag,
1670                           &wmi_data->rs);
1671
1672         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1673 }
1674
1675 static void handle_rc_rate_update_cmd(void *Context, A_UINT16 Command,
1676                                       A_UINT16 SeqNo, A_UINT8 *buffer, a_int32_t Length)
1677 {
1678         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1679         struct wmi_rc_rate_update_cmd *wmi_data = (struct wmi_rc_rate_update_cmd *)buffer;
1680
1681         a_uint32_t capflag = adf_os_ntohl(wmi_data->capflag);
1682
1683         ath_rate_node_update(sc, &sc->sc_sta[wmi_data->node_index],
1684                              wmi_data->isNew,
1685                              capflag,
1686                              &wmi_data->rs);
1687
1688         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1689 }
1690
1691 static void dispatch_magpie_sys_cmds(void *pContext, A_UINT16 Command,
1692                                      A_UINT16 SeqNo, A_UINT8 *buffer, a_int32_t Length)
1693 {
1694         adf_os_assert(0);
1695 }
1696
1697 static void ath_rc_mask_tgt(void *Context, A_UINT16 Command,
1698                             A_UINT16 SeqNo, A_UINT8 *buffer, a_int32_t Length)
1699 {
1700         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)Context;
1701         struct wmi_rc_rate_mask_cmd *wmi_data = (struct wmi_rc_rate_mask_cmd *)buffer;
1702         int idx, band, i;
1703
1704         idx = wmi_data->vap_index;
1705         band = wmi_data->band;
1706
1707         sc->sc_vap[idx].av_rate_mask[band] = adf_os_ntohl(wmi_data->mask);
1708
1709         if (sc->sc_vap[idx].av_rate_mask[band]) {
1710                 for (i = 0; i < RATE_TABLE_SIZE; i++) {
1711                         if ((1 << i) & sc->sc_vap[idx].av_rate_mask[band]) {
1712                                 sc->sc_vap[idx].av_minrateidx[band] = i;
1713                                 break;
1714                         }
1715                 }
1716         } else {
1717                 sc->sc_vap[idx].av_minrateidx[band] = 0;
1718         }
1719
1720         wmi_cmd_rsp(sc->tgt_wmi_handle, Command, SeqNo, NULL, 0);
1721 }
1722
1723 static WMI_DISPATCH_ENTRY Magpie_Sys_DispatchEntries[] =
1724 {
1725         {handle_echo_command,         WMI_ECHO_CMDID,               0},
1726         {dispatch_magpie_sys_cmds,    WMI_ACCESS_MEMORY_CMDID,      0},
1727         {ath_get_tgt_version,         WMI_GET_FW_VERSION,           0},
1728         {ath_disable_intr_tgt,        WMI_DISABLE_INTR_CMDID,       0},
1729         {ath_enable_intr_tgt,         WMI_ENABLE_INTR_CMDID,        0},
1730         {ath_init_tgt,                WMI_ATH_INIT_CMDID,           0},
1731         {ath_aborttxq_tgt,            WMI_ABORT_TXQ_CMDID,          0},
1732         {ath_stop_tx_dma_tgt,         WMI_STOP_TX_DMA_CMDID,        0},
1733         {ath_aborttx_dma_tgt,         WMI_ABORT_TX_DMA_CMDID,       0},
1734         {ath_tx_draintxq_tgt,         WMI_DRAIN_TXQ_CMDID,          0},
1735         {ath_draintxq_tgt,            WMI_DRAIN_TXQ_ALL_CMDID,      0},
1736         {ath_startrecv_tgt,           WMI_START_RECV_CMDID,         0},
1737         {ath_stoprecv_tgt,            WMI_STOP_RECV_CMDID,          0},
1738         {ath_flushrecv_tgt,           WMI_FLUSH_RECV_CMDID,         0},
1739         {ath_setcurmode_tgt,          WMI_SET_MODE_CMDID,           0},
1740         {ath_node_create_tgt,         WMI_NODE_CREATE_CMDID,        0},
1741         {ath_node_cleanup_tgt,        WMI_NODE_REMOVE_CMDID,        0},
1742         {ath_vap_delete_tgt,          WMI_VAP_REMOVE_CMDID,         0},
1743         {ath_vap_create_tgt,          WMI_VAP_CREATE_CMDID,         0},
1744         {ath_hal_reg_read_tgt,        WMI_REG_READ_CMDID,           0},
1745         {ath_hal_reg_write_tgt,       WMI_REG_WRITE_CMDID,          0},
1746         {handle_rc_state_change_cmd,  WMI_RC_STATE_CHANGE_CMDID,    0},
1747         {handle_rc_rate_update_cmd,   WMI_RC_RATE_UPDATE_CMDID,     0},
1748         {ath_ic_update_tgt,           WMI_TARGET_IC_UPDATE_CMDID,   0},
1749         {ath_enable_aggr_tgt,         WMI_TX_AGGR_ENABLE_CMDID,     0},
1750         {ath_detach_tgt,              WMI_TGT_DETACH_CMDID,         0},
1751         {ath_node_update_tgt,         WMI_NODE_UPDATE_CMDID,        0},
1752         {ath_int_stats_tgt,           WMI_INT_STATS_CMDID,          0},
1753         {ath_tx_stats_tgt,            WMI_TX_STATS_CMDID,           0},
1754         {ath_rx_stats_tgt,            WMI_RX_STATS_CMDID,           0},
1755         {ath_rc_mask_tgt,             WMI_BITRATE_MASK_CMDID,       0},
1756 };
1757
1758 /*****************/
1759 /* Init / Deinit */
1760 /*****************/
1761
1762 static void htc_setup_comp(void)
1763 {
1764 }
1765
1766 static A_UINT8 tgt_ServiceConnect(HTC_SERVICE *pService,
1767                                   HTC_ENDPOINT_ID eid,
1768                                   A_UINT8 *pDataIn,
1769                                   a_int32_t LengthIn,
1770                                   A_UINT8 *pDataOut,
1771                                   a_int32_t *pLengthOut)
1772 {
1773         struct ath_softc_tgt *sc = (struct ath_softc_tgt *)pService->ServiceCtx;
1774
1775         switch(pService->ServiceID) {
1776         case WMI_CONTROL_SVC:
1777                 sc->wmi_command_ep= eid;
1778                 break;
1779         case WMI_BEACON_SVC:
1780                 sc->beacon_ep= eid;
1781                 break;
1782         case WMI_CAB_SVC:
1783                 sc->cab_ep= eid;
1784                 break;
1785         case WMI_UAPSD_SVC:
1786                 sc->uapsd_ep= eid;
1787                 break;
1788         case WMI_MGMT_SVC:
1789                 sc->mgmt_ep= eid;
1790                 break;
1791         case WMI_DATA_VO_SVC:
1792                 sc->data_VO_ep = eid;
1793                 break;
1794         case WMI_DATA_VI_SVC:
1795                 sc->data_VI_ep = eid;
1796                 break;
1797         case WMI_DATA_BE_SVC:
1798                 sc->data_BE_ep = eid;
1799                 break;
1800         case WMI_DATA_BK_SVC:
1801                 sc->data_BK_ep = eid;
1802                 break;
1803         default:
1804                 adf_os_assert(0);
1805         }
1806
1807         return HTC_SERVICE_SUCCESS;
1808 }
1809
1810 static void tgt_reg_service(struct ath_softc_tgt *sc, HTC_SERVICE *svc,
1811                             int svcId, HTC_SERVICE_ProcessRecvMsg recvMsg)
1812 {
1813         svc->ProcessRecvMsg = recvMsg;
1814         svc->ProcessSendBufferComplete = tgt_HTCSendCompleteHandler;
1815         svc->ProcessConnect = tgt_ServiceConnect;
1816         svc->MaxSvcMsgSize = 1600;
1817         svc->TrailerSpcCheckLimit = 0;
1818         svc->ServiceID = svcId;
1819         svc->ServiceCtx = sc;
1820         HTC_RegisterService(sc->tgt_htc_handle, svc);
1821 }
1822
1823 static void tgt_hif_htc_wmi_init(struct ath_softc_tgt *sc)
1824 {
1825         HTC_CONFIG htc_conf;
1826         WMI_SVC_CONFIG wmiConfig;
1827         WMI_DISPATCH_TABLE *Magpie_Sys_Commands_Tbl;
1828
1829         /* Init dynamic buf pool */
1830         sc->pool_handle = BUF_Pool_init(sc->sc_hdl);
1831
1832         /* Init target-side HIF */
1833         sc->tgt_hif_handle = HIF_init(0);
1834
1835         /* Init target-side HTC */
1836         htc_conf.HIFHandle = sc->tgt_hif_handle;
1837         htc_conf.CreditSize = 320;
1838         htc_conf.CreditNumber = ATH_TXBUF;
1839         htc_conf.OSHandle = sc->sc_hdl;
1840         htc_conf.PoolHandle = sc->pool_handle;
1841         sc->tgt_htc_handle = HTC_init(htc_setup_comp, &htc_conf);
1842 #if defined(PROJECT_MAGPIE)
1843         init_htc_handle = sc->tgt_htc_handle;
1844 #endif
1845
1846         tgt_reg_service(sc, &sc->htc_beacon_service, WMI_BEACON_SVC, tgt_HTCRecv_beaconhandler);
1847         tgt_reg_service(sc, &sc->htc_cab_service, WMI_CAB_SVC, tgt_HTCRecv_cabhandler);
1848         tgt_reg_service(sc, &sc->htc_uapsd_service, WMI_UAPSD_SVC, tgt_HTCRecv_uapsdhandler);
1849         tgt_reg_service(sc, &sc->htc_mgmt_service, WMI_MGMT_SVC, tgt_HTCRecv_mgmthandler);
1850         tgt_reg_service(sc, &sc->htc_data_BE_service, WMI_DATA_BE_SVC, tgt_HTCRecvMessageHandler);
1851         tgt_reg_service(sc, &sc->htc_data_BK_service, WMI_DATA_BK_SVC, tgt_HTCRecvMessageHandler);
1852         tgt_reg_service(sc, &sc->htc_data_VI_service, WMI_DATA_VI_SVC, tgt_HTCRecvMessageHandler);
1853         tgt_reg_service(sc, &sc->htc_data_VO_service, WMI_DATA_VO_SVC, tgt_HTCRecvMessageHandler);
1854
1855         /* Init target-side WMI */
1856         Magpie_Sys_Commands_Tbl = (WMI_DISPATCH_TABLE *)adf_os_mem_alloc(sizeof(WMI_DISPATCH_TABLE));
1857         adf_os_mem_zero(Magpie_Sys_Commands_Tbl, sizeof(WMI_DISPATCH_TABLE));
1858         Magpie_Sys_Commands_Tbl->NumberOfEntries = WMI_DISPATCH_ENTRY_COUNT(Magpie_Sys_DispatchEntries);
1859         Magpie_Sys_Commands_Tbl->pTable = Magpie_Sys_DispatchEntries;
1860
1861         adf_os_mem_zero(&wmiConfig, sizeof(WMI_SVC_CONFIG));
1862         wmiConfig.HtcHandle = sc->tgt_htc_handle;
1863         wmiConfig.PoolHandle = sc->pool_handle;
1864         wmiConfig.MaxCmdReplyEvts = ATH_WMI_MAX_CMD_REPLY;
1865         wmiConfig.MaxEventEvts = ATH_WMI_MAX_EVENTS;
1866
1867         sc->tgt_wmi_handle = WMI_Init(&wmiConfig);
1868         Magpie_Sys_Commands_Tbl->pContext = sc;
1869         WMI_RegisterDispatchTable(sc->tgt_wmi_handle, Magpie_Sys_Commands_Tbl);
1870
1871         HTC_NotifyTargetInserted(sc->tgt_htc_handle);
1872
1873         /* Start HTC messages exchange */
1874         HTC_Ready(sc->tgt_htc_handle);
1875 }
1876
1877 a_int32_t ath_tgt_attach(a_uint32_t devid, struct ath_softc_tgt *sc, adf_os_device_t osdev)
1878 {
1879         struct ath_hal *ah;
1880         HAL_STATUS status;
1881         a_int32_t error = 0, i, flags = 0;
1882         a_uint8_t csz;
1883
1884         adf_os_pci_config_read8(osdev, ATH_PCI_CACHE_LINE_SIZE, &csz);
1885
1886         if (csz == 0)
1887                 csz = 16;
1888         sc->sc_cachelsz = csz << 2;
1889
1890         sc->sc_dev = osdev;
1891         sc->sc_hdl = osdev;
1892
1893         ATH_INIT_TQUEUE(sc->sc_dev, &sc->sc_rxtq, ath_tgt_rx_tasklet, sc);
1894         ATH_INIT_TQUEUE(sc->sc_dev, &sc->sc_txtq, owl_tgt_tx_tasklet, sc);
1895         ATH_INIT_TQUEUE(sc->sc_dev, &sc->sc_bmisstq, ath_bmiss_tasklet, sc);
1896         ATH_INIT_TQUEUE(sc->sc_dev, &sc->sc_fataltq, ath_fatal_tasklet, sc);
1897
1898         flags |= AH_USE_EEPROM;
1899         ah = _ath_hal_attach_tgt(devid, sc, sc->sc_dev, flags, &status);
1900         if (ah == NULL) {
1901                 error = ENXIO;
1902                 goto bad;
1903         }
1904         sc->sc_ah = ah;
1905
1906         tgt_hif_htc_wmi_init(sc);
1907
1908         sc->sc_bhalq = HAL_NUM_TX_QUEUES - 1;
1909
1910         ath_rate_setup(sc, IEEE80211_MODE_11NA);
1911         ath_rate_setup(sc, IEEE80211_MODE_11NG);
1912
1913         sc->sc_rc = ath_rate_attach(sc);
1914         if (sc->sc_rc == NULL) {
1915                 error = EIO;
1916                 goto bad2;
1917         }
1918
1919         for (i=0; i < TARGET_NODE_MAX; i++) {
1920                 sc->sc_sta[i].an_rcnode = adf_os_mem_alloc(sc->sc_rc->arc_space);
1921         }
1922
1923         error = ath_desc_alloc(sc);
1924         if (error != 0) {
1925                 goto bad;
1926         }
1927
1928         BUF_Pool_create_pool(sc->pool_handle, POOL_ID_WLAN_RX_BUF, ath_numrxdescs, 1664);
1929
1930         ath_tgt_txq_setup(sc);
1931         sc->sc_imask =0;
1932         ath_hal_intrset(ah,0);
1933
1934         return 0;
1935 bad:
1936 bad2:
1937         ath_desc_free(sc);
1938         if (ah)
1939                 ath_hal_detach(ah);
1940 }
1941
1942 static void tgt_hif_htc_wmi_shutdown(struct ath_softc_tgt *sc)
1943 {
1944         HTC_NotifyTargetDetached(sc->tgt_htc_handle);
1945
1946         WMI_Shutdown(sc->tgt_wmi_handle);
1947         HTC_Shutdown(sc->tgt_htc_handle);
1948         HIF_shutdown(sc->tgt_hif_handle);
1949         BUF_Pool_shutdown(sc->pool_handle);
1950 }
1951
1952 a_int32_t ath_detach(struct ath_softc_tgt *sc)
1953 {
1954         tgt_hif_htc_wmi_shutdown(sc);
1955 }