Initial commit
[kernel/linux-3.0.git] / drivers / staging / ath6kl / wmi / wmi.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Corporation.  All rights reserved.
3 // 
4 //
5 // Permission to use, copy, modify, and/or distribute this software for any
6 // purpose with or without fee is hereby granted, provided that the above
7 // copyright notice and this permission notice appear in all copies.
8 //
9 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 //
17 //
18 //------------------------------------------------------------------------------
19 //==============================================================================
20 // This module implements the hardware independent layer of the
21 // Wireless Module Interface (WMI) protocol.
22 //
23 // Author(s): ="Atheros"
24 //==============================================================================
25
26 #include <a_config.h>
27 #include <athdefs.h>
28 #include <a_osapi.h>
29 #include "htc.h"
30 #include "htc_api.h"
31 #include "wmi.h"
32 #include <wlan_api.h>
33 #include <wmi_api.h>
34 #include <ieee80211.h>
35 #include <ieee80211_node.h>
36 #include "dset_api.h"
37 #include "wmi_host.h"
38 #include "a_drv.h"
39 #include "a_drv_api.h"
40 #define ATH_MODULE_NAME wmi
41 #include "a_debug.h"
42 #include "dbglog_api.h"
43 #include "roaming.h"
44
45 #define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
46
47 #ifdef ATH_DEBUG_MODULE
48
49 static struct ath_debug_mask_description wmi_debug_desc[] = {
50     { ATH_DEBUG_WMI , "General WMI Tracing"},
51 };
52
53 ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi,
54                                  "wmi",
55                                  "Wireless Module Interface",
56                                  ATH_DEBUG_MASK_DEFAULTS,
57                                  ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc),
58                                  wmi_debug_desc);
59
60 #endif
61
62 #ifndef REXOS
63 #define DBGARG      _A_FUNCNAME_
64 #define DBGFMT      "%s() : "
65 #define DBG_WMI     ATH_DEBUG_WMI
66 #define DBG_ERROR   ATH_DEBUG_ERR
67 #define DBG_WMI2    ATH_DEBUG_WMI
68 #define A_DPRINTF   AR_DEBUG_PRINTF
69 #endif
70
71 static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
72
73 static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
74                                      int len);
75 static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
76                                         int len);
77
78 static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
79                                         int len);
80 static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
81                                      int len);
82 static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
83                                        int len);
84 static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
85                                      int len);
86 static int wmi_sync_point(struct wmi_t *wmip);
87
88 static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
89                                      int len);
90 static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
91                                      int len);
92 static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
93                                          int len);
94 static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
95                                        int len);
96 static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
97 static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
98                                              int len);
99
100 static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
101                                      int len);
102 #ifdef CONFIG_HOST_DSET_SUPPORT
103 static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
104 static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
105                                      int len);
106 #endif /* CONFIG_HOST_DSET_SUPPORT */
107
108
109 static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
110                                      int len);
111 static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
112 static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
113 static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
114 static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
115 static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
116 static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
117 static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
118 static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
119                                       int len);
120 static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
121                                       int len);
122 static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
123                                       int len);
124 static int
125 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
126
127 static int
128 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
129
130
131 #ifdef CONFIG_HOST_TCMD_SUPPORT
132 static int
133 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
134 #endif
135
136 static int
137 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
138
139 static int
140 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
141
142 static int
143 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
144
145 static bool
146 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
147
148 static int
149 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
150
151 static int
152 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
153
154 static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
155
156 int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
157                   WMI_SYNC_FLAG syncflag);
158
159 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
160 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
161
162 void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
163 void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
164 static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
165                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
166 static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
167                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
168 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
169 static int
170 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
171 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
172
173 static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
174                                      int len);
175 static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
176                                      int len);
177
178 static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
179                                         int len);
180 static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
181 static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
182 static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
183 static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
184 static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
185 static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
186
187 #ifdef WAPI_ENABLE
188 static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
189                                      int len);
190 #endif
191
192 #if defined(UNDER_CE)
193 #if defined(NDIS51_MINIPORT)
194 unsigned int processDot11Hdr = 0;
195 #else
196 unsigned int processDot11Hdr = 1;
197 #endif
198 #else
199 extern unsigned int processDot11Hdr;
200 #endif
201
202 int wps_enable;
203 static const s32 wmi_rateTable[][2] = {
204   //{W/O SGI, with SGI}
205     {1000, 1000},
206     {2000, 2000},
207     {5500, 5500},
208     {11000, 11000},
209     {6000, 6000},
210     {9000, 9000},
211     {12000, 12000},
212     {18000, 18000},
213     {24000, 24000},
214     {36000, 36000},
215     {48000, 48000},
216     {54000, 54000},
217     {6500, 7200},
218     {13000, 14400},
219     {19500, 21700},
220     {26000, 28900},
221     {39000, 43300},
222     {52000, 57800},
223     {58500, 65000},
224     {65000, 72200},
225     {13500, 15000},
226     {27000, 30000},
227     {40500, 45000},
228     {54000, 60000},
229     {81000, 90000},
230     {108000, 120000},
231     {121500, 135000},
232     {135000, 150000},
233     {0, 0}};
234
235 #define MODE_A_SUPPORT_RATE_START       ((s32) 4)
236 #define MODE_A_SUPPORT_RATE_STOP        ((s32) 11)
237
238 #define MODE_GONLY_SUPPORT_RATE_START   MODE_A_SUPPORT_RATE_START
239 #define MODE_GONLY_SUPPORT_RATE_STOP    MODE_A_SUPPORT_RATE_STOP
240
241 #define MODE_B_SUPPORT_RATE_START       ((s32) 0)
242 #define MODE_B_SUPPORT_RATE_STOP        ((s32) 3)
243
244 #define MODE_G_SUPPORT_RATE_START       ((s32) 0)
245 #define MODE_G_SUPPORT_RATE_STOP        ((s32) 11)
246
247 #define MODE_GHT20_SUPPORT_RATE_START   ((s32) 0)
248 #define MODE_GHT20_SUPPORT_RATE_STOP    ((s32) 19)
249
250 #define MAX_NUMBER_OF_SUPPORT_RATES     (MODE_GHT20_SUPPORT_RATE_STOP + 1)
251
252 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
253 const u8 up_to_ac[]= {
254                 WMM_AC_BE,
255                 WMM_AC_BK,
256                 WMM_AC_BK,
257                 WMM_AC_BE,
258                 WMM_AC_VI,
259                 WMM_AC_VI,
260                 WMM_AC_VO,
261                 WMM_AC_VO,
262             };
263
264 /* This stuff is used when we want a simple layer-3 visibility */
265 typedef PREPACK struct _iphdr {
266     u8 ip_ver_hdrlen;          /* version and hdr length */
267     u8 ip_tos;                 /* type of service */
268     u16 ip_len;                 /* total length */
269     u16 ip_id;                  /* identification */
270     s16 ip_off;                 /* fragment offset field */
271 #define IP_DF 0x4000                    /* dont fragment flag */
272 #define IP_MF 0x2000                    /* more fragments flag */
273 #define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
274     u8 ip_ttl;                 /* time to live */
275     u8 ip_p;                   /* protocol */
276     u16 ip_sum;                 /* checksum */
277     u8 ip_src[4];              /* source and dest address */
278     u8 ip_dst[4];
279 } POSTPACK iphdr;
280
281 static s16 rssi_event_value = 0;
282 static s16 snr_event_value = 0;
283
284 bool is_probe_ssid = false;
285
286 void *
287 wmi_init(void *devt)
288 {
289     struct wmi_t *wmip;
290
291     A_REGISTER_MODULE_DEBUG_INFO(wmi);
292
293     wmip = A_MALLOC (sizeof(struct wmi_t));
294     if (wmip == NULL) {
295         return (NULL);
296     }
297     A_MEMZERO(wmip, sizeof(struct wmi_t ));
298 #ifdef THREAD_X
299     INIT_WMI_LOCK(wmip);
300 #else
301         A_MUTEX_INIT(&wmip->wmi_lock);
302 #endif
303     wmip->wmi_devt = devt;
304     wlan_node_table_init(wmip, &wmip->wmi_scan_table);
305     wmi_qos_state_init(wmip);
306
307     wmip->wmi_powerMode = REC_POWER;
308     wmip->wmi_phyMode = WMI_11G_MODE;
309
310     wmip->wmi_pair_crypto_type  = NONE_CRYPT;
311     wmip->wmi_grp_crypto_type   = NONE_CRYPT;
312
313     wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1;
314     wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1;
315
316     return (wmip);
317 }
318
319 void
320 wmi_qos_state_init(struct wmi_t *wmip)
321 {
322     u8 i;
323
324     if (wmip == NULL) {
325         return;
326     }
327     LOCK_WMI(wmip);
328
329     /* Initialize QoS States */
330     wmip->wmi_numQoSStream = 0;
331
332     wmip->wmi_fatPipeExists = 0;
333
334     for (i=0; i < WMM_NUM_AC; i++) {
335         wmip->wmi_streamExistsForAC[i]=0;
336     }
337
338     UNLOCK_WMI(wmip);
339
340     A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
341 }
342
343 void
344 wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid)
345 {
346     A_ASSERT( eid != ENDPOINT_UNUSED);
347     wmip->wmi_endpoint_id = eid;
348 }
349
350 HTC_ENDPOINT_ID
351 wmi_get_control_ep(struct wmi_t * wmip)
352 {
353     return(wmip->wmi_endpoint_id);
354 }
355
356 void
357 wmi_shutdown(struct wmi_t *wmip)
358 {
359     if (wmip != NULL) {
360         wlan_node_table_cleanup(&wmip->wmi_scan_table);
361         if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
362 #ifdef THREAD_X
363             DELETE_WMI_LOCK(&wmip);
364 #else
365             A_MUTEX_DELETE(&wmip->wmi_lock);
366 #endif
367         }
368         kfree(wmip);
369     }
370 }
371
372 /*
373  *  performs DIX to 802.3 encapsulation for transmit packets.
374  *  uses passed in buffer.  Returns buffer or NULL if failed.
375  *  Assumes the entire DIX header is contigous and that there is
376  *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
377  */
378 int
379 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
380 {
381     u8 *datap;
382     u16 typeorlen;
383     ATH_MAC_HDR      macHdr;
384     ATH_LLC_SNAP_HDR *llcHdr;
385
386     A_ASSERT(osbuf != NULL);
387
388     if (A_NETBUF_HEADROOM(osbuf) <
389         (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
390     {
391         return A_NO_MEMORY;
392     }
393
394     datap = A_NETBUF_DATA(osbuf);
395
396     typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
397
398     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
399         /*
400          * packet is already in 802.3 format - return success
401          */
402         A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
403         return (0);
404     }
405
406     /*
407      * Save mac fields and length to be inserted later
408      */
409     memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
410     memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
411     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
412                                   sizeof(ATH_LLC_SNAP_HDR));
413
414     /*
415      * Make room for LLC+SNAP headers
416      */
417     if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
418         return A_NO_MEMORY;
419     }
420     datap = A_NETBUF_DATA(osbuf);
421
422     memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
423
424     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
425     llcHdr->dsap      = 0xAA;
426     llcHdr->ssap      = 0xAA;
427     llcHdr->cntl      = 0x03;
428     llcHdr->orgCode[0] = 0x0;
429     llcHdr->orgCode[1] = 0x0;
430     llcHdr->orgCode[2] = 0x0;
431     llcHdr->etherType = typeorlen;
432
433     return (0);
434 }
435
436 int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
437 {
438     switch(*pVersion){
439         case 0:
440                 return (0);
441         case WMI_META_VERSION_1:
442                 {
443                 WMI_TX_META_V1     *pV1= NULL;
444                 A_ASSERT(osbuf != NULL);
445                 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
446                         return A_NO_MEMORY;
447                 }
448
449                 pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf);
450                 /* the pktID is used in conjunction with txComplete messages
451                 * allowing the target to notify which tx requests have been
452                 * completed and how. */
453                 pV1->pktID = 0;
454                 /* the ratePolicyID allows the host to specify which rate policy
455                 * to use for transmitting this packet. 0 means use default behavior. */
456                 pV1->ratePolicyID = 0;
457                 A_ASSERT(pVersion != NULL);
458                 /* the version must be used to populate the meta field of the WMI_DATA_HDR */
459                 *pVersion = WMI_META_VERSION_1;
460                 return (0);
461                 }
462         case WMI_META_VERSION_2:
463                 {
464                 WMI_TX_META_V2 *pV2 ;
465                 A_ASSERT(osbuf != NULL);
466                 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
467                         return A_NO_MEMORY;
468                 }
469                 pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
470                 memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
471                 return (0);
472                 }
473         default:
474                 return (0);
475     }
476 }
477
478 /* Adds a WMI data header */
479 int
480 wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
481                     WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
482 {
483     WMI_DATA_HDR     *dtHdr;
484 //    u8 metaVersion = 0;
485     int status;
486
487     A_ASSERT(osbuf != NULL);
488
489     /* adds the meta data field after the wmi data hdr. If metaVersion
490      * is returns 0 then no meta field was added. */
491     if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
492         return status;
493     }
494
495     if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
496         return A_NO_MEMORY;
497     }
498
499     dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
500     A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR));
501
502     WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType);
503     WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type);
504
505     if (bMoreData) {
506         WMI_DATA_HDR_SET_MORE_BIT(dtHdr);
507     }
508
509     WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
510
511     dtHdr->info3 = 0;
512
513     return (0);
514 }
515
516
517 u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
518 {
519     u8 *datap;
520     u8 trafficClass = WMM_AC_BE;
521     u16 ipType = IP_ETHERTYPE;
522     WMI_DATA_HDR    *dtHdr;
523     u8 streamExists = 0;
524     u8 userPriority;
525     u32 hdrsize, metasize;
526     ATH_LLC_SNAP_HDR    *llcHdr;
527
528     WMI_CREATE_PSTREAM_CMD  cmd;
529
530     A_ASSERT(osbuf != NULL);
531
532     //
533     // Initialize header size
534     //
535     hdrsize = 0;
536
537     datap = A_NETBUF_DATA(osbuf);
538     dtHdr = (WMI_DATA_HDR *)datap;
539     metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0;
540
541     if (!wmmEnabled)
542     {
543             /* If WMM is disabled all traffic goes as BE traffic */
544         userPriority = 0;
545     }
546     else
547     {
548         if (processDot11Hdr)
549         {
550              hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
551              llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
552                           hdrsize);
553
554
555         }
556         else
557         {
558             llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
559                           sizeof(ATH_MAC_HDR));
560         }
561
562         if (llcHdr->etherType == A_CPU2BE16(ipType))
563         {
564             /* Extract the endpoint info from the TOS field in the IP header */
565
566             userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
567         }
568         else
569         {
570             userPriority = layer2Priority & 0x7;
571         }
572     }
573
574
575     /* workaround for WMM S5 */
576     if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority)))
577     {
578         userPriority = 1;
579     }
580
581     trafficClass = convert_userPriority_to_trafficClass(userPriority);
582
583     WMI_DATA_HDR_SET_UP(dtHdr, userPriority);
584     /* lower 3-bits are 802.1d priority */
585     //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;
586
587     LOCK_WMI(wmip);
588     streamExists = wmip->wmi_fatPipeExists;
589     UNLOCK_WMI(wmip);
590
591     if (!(streamExists & (1 << trafficClass)))
592     {
593
594         A_MEMZERO(&cmd, sizeof(cmd));
595         cmd.trafficClass = trafficClass;
596         cmd.userPriority = userPriority;
597         cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
598             /* Implicit streams are created with TSID 0xFF */
599
600         cmd.tsid = WMI_IMPLICIT_PSTREAM;
601         wmi_create_pstream_cmd(wmip, &cmd);
602     }
603
604     return trafficClass;
605 }
606
607 int
608 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
609 {
610     u8 *datap;
611     u16 typeorlen;
612     ATH_MAC_HDR      macHdr;
613     ATH_LLC_SNAP_HDR *llcHdr;
614     struct           ieee80211_frame *wh;
615     u32 hdrsize;
616
617     A_ASSERT(osbuf != NULL);
618
619     if (A_NETBUF_HEADROOM(osbuf) <
620         (sizeof(struct ieee80211_qosframe) +  sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
621     {
622         return A_NO_MEMORY;
623     }
624
625     datap = A_NETBUF_DATA(osbuf);
626
627     typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
628
629     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
630 /*
631          * packet is already in 802.3 format - return success
632          */
633         A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
634         goto AddDot11Hdr;
635     }
636
637     /*
638      * Save mac fields and length to be inserted later
639      */
640     memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
641     memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
642     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
643                                   sizeof(ATH_LLC_SNAP_HDR));
644
645     // Remove the Ethernet hdr
646     A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR));
647     /*
648      * Make room for LLC+SNAP headers
649      */
650     if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
651         return A_NO_MEMORY;
652     }
653     datap = A_NETBUF_DATA(osbuf);
654
655     llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
656     llcHdr->dsap       = 0xAA;
657     llcHdr->ssap       = 0xAA;
658     llcHdr->cntl       = 0x03;
659     llcHdr->orgCode[0] = 0x0;
660     llcHdr->orgCode[1] = 0x0;
661     llcHdr->orgCode[2] = 0x0;
662     llcHdr->etherType  = typeorlen;
663
664 AddDot11Hdr:
665     /* Make room for 802.11 hdr */
666     if (wmip->wmi_is_wmm_enabled)
667     {
668         hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
669         if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
670         {
671             return A_NO_MEMORY;
672         }
673         wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
674         wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS;
675     }
676     else
677     {
678         hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
679         if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
680         {
681             return A_NO_MEMORY;
682         }
683         wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
684         wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA;
685     }
686     /* Setup the SA & DA */
687     IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac);
688
689     if (mode == INFRA_NETWORK) {
690         IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac);
691     }
692     else if (mode == ADHOC_NETWORK) {
693         IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
694     }
695
696     return (0);
697 }
698
699 int
700 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
701 {
702     u8 *datap;
703     struct           ieee80211_frame *pwh,wh;
704     u8 type,subtype;
705     ATH_LLC_SNAP_HDR *llcHdr;
706     ATH_MAC_HDR      macHdr;
707     u32 hdrsize;
708
709     A_ASSERT(osbuf != NULL);
710     datap = A_NETBUF_DATA(osbuf);
711
712     pwh = (struct ieee80211_frame *)datap;
713     type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
714     subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
715
716     memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
717
718     /* strip off the 802.11 hdr*/
719     if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
720         hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
721         A_NETBUF_PULL(osbuf, hdrsize);
722     } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
723         A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
724     }
725
726     datap = A_NETBUF_DATA(osbuf);
727     llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
728
729     macHdr.typeOrLen = llcHdr->etherType;
730     A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac));
731     A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac));
732
733     switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
734     case IEEE80211_FC1_DIR_NODS:
735         IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
736         IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
737         break;
738     case IEEE80211_FC1_DIR_TODS:
739         IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3);
740         IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
741         break;
742     case IEEE80211_FC1_DIR_FROMDS:
743         IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
744         IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3);
745         break;
746     case IEEE80211_FC1_DIR_DSTODS:
747         break;
748     }
749
750     // Remove the LLC Hdr.
751     A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR));
752
753     // Insert the ATH MAC hdr.
754
755     A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
756     datap = A_NETBUF_DATA(osbuf);
757
758     memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
759
760     return 0;
761 }
762
763 /*
764  *  performs 802.3 to DIX encapsulation for received packets.
765  *  Assumes the entire 802.3 header is contigous.
766  */
767 int
768 wmi_dot3_2_dix(void *osbuf)
769 {
770     u8 *datap;
771     ATH_MAC_HDR      macHdr;
772     ATH_LLC_SNAP_HDR *llcHdr;
773
774     A_ASSERT(osbuf != NULL);
775     datap = A_NETBUF_DATA(osbuf);
776
777     memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
778     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
779     macHdr.typeOrLen = llcHdr->etherType;
780
781     if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
782         return A_NO_MEMORY;
783     }
784
785     datap = A_NETBUF_DATA(osbuf);
786
787     memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
788
789     return (0);
790 }
791
792 /*
793  * Removes a WMI data header
794  */
795 int
796 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
797 {
798     A_ASSERT(osbuf != NULL);
799
800     return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
801 }
802
803 void
804 wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
805 {
806     wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
807 }
808
809 /*
810  * WMI Extended Event received from Target.
811  */
812 int
813 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
814 {
815     WMIX_CMD_HDR *cmd;
816     u16 id;
817     u8 *datap;
818     u32 len;
819     int status = 0;
820
821     if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
822         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
823         wmip->wmi_stats.cmd_len_err++;
824         return A_ERROR;
825     }
826
827     cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
828     id = cmd->commandId;
829
830     if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
831         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
832         wmip->wmi_stats.cmd_len_err++;
833         return A_ERROR;
834     }
835
836     datap = A_NETBUF_DATA(osbuf);
837     len = A_NETBUF_LEN(osbuf);
838
839     switch (id) {
840     case (WMIX_DSETOPENREQ_EVENTID):
841         status = wmi_dset_open_req_rx(wmip, datap, len);
842         break;
843 #ifdef CONFIG_HOST_DSET_SUPPORT
844     case (WMIX_DSETCLOSE_EVENTID):
845         status = wmi_dset_close_rx(wmip, datap, len);
846         break;
847     case (WMIX_DSETDATAREQ_EVENTID):
848         status = wmi_dset_data_req_rx(wmip, datap, len);
849         break;
850 #endif /* CONFIG_HOST_DSET_SUPPORT */
851     case (WMIX_HB_CHALLENGE_RESP_EVENTID):
852         wmi_hbChallengeResp_rx(wmip, datap, len);
853         break;
854     case (WMIX_DBGLOG_EVENTID):
855         wmi_dbglog_event_rx(wmip, datap, len);
856         break;
857 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
858     case (WMIX_PROF_COUNT_EVENTID):
859         wmi_prof_count_rx(wmip, datap, len);
860         break;
861 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
862     default:
863         A_DPRINTF(DBG_WMI|DBG_ERROR,
864             (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
865         wmip->wmi_stats.cmd_id_err++;
866         status = A_ERROR;
867         break;
868     }
869
870     return status;
871 }
872
873 /*
874  * Control Path
875  */
876 u32 cmdRecvNum;
877
878 int
879 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
880 {
881     WMI_CMD_HDR *cmd;
882     u16 id;
883     u8 *datap;
884     u32 len, i, loggingReq;
885     int status = 0;
886
887     A_ASSERT(osbuf != NULL);
888     if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
889         A_NETBUF_FREE(osbuf);
890         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
891         wmip->wmi_stats.cmd_len_err++;
892         return A_ERROR;
893     }
894
895     cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
896     id = cmd->commandId;
897
898     if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
899         A_NETBUF_FREE(osbuf);
900         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
901         wmip->wmi_stats.cmd_len_err++;
902         return A_ERROR;
903     }
904
905     datap = A_NETBUF_DATA(osbuf);
906     len = A_NETBUF_LEN(osbuf);
907
908     loggingReq = 0;
909
910     ar6000_get_driver_cfg(wmip->wmi_devt,
911                     AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
912                     &loggingReq);
913
914     if(loggingReq) {
915         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
916         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
917         for(i = 0; i < len; i++)
918             AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
919         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
920     }
921
922     LOCK_WMI(wmip);
923     cmdRecvNum++;
924     UNLOCK_WMI(wmip);
925
926     switch (id) {
927     case (WMI_GET_BITRATE_CMDID):
928         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
929         status = wmi_bitrate_reply_rx(wmip, datap, len);
930         break;
931     case (WMI_GET_CHANNEL_LIST_CMDID):
932         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
933         status = wmi_channelList_reply_rx(wmip, datap, len);
934         break;
935     case (WMI_GET_TX_PWR_CMDID):
936         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
937         status = wmi_txPwr_reply_rx(wmip, datap, len);
938         break;
939     case (WMI_READY_EVENTID):
940         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
941         status = wmi_ready_event_rx(wmip, datap, len);
942         A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
943         break;
944     case (WMI_CONNECT_EVENTID):
945         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
946         status = wmi_connect_event_rx(wmip, datap, len);
947         break;
948     case (WMI_DISCONNECT_EVENTID):
949         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
950         status = wmi_disconnect_event_rx(wmip, datap, len);
951         break;
952     case (WMI_PEER_NODE_EVENTID):
953         A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG));
954         status = wmi_peer_node_event_rx(wmip, datap, len);
955         break;
956     case (WMI_TKIP_MICERR_EVENTID):
957         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
958         status = wmi_tkip_micerr_event_rx(wmip, datap, len);
959         break;
960     case (WMI_BSSINFO_EVENTID):
961         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
962         {
963             /*
964              * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR
965              * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer
966              * and reconstruct the WMI_BSS_INFO_HDR in its place
967             */
968             WMI_BSS_INFO_HDR2 bih2;
969             WMI_BSS_INFO_HDR *bih;
970             memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
971
972             A_NETBUF_PUSH(osbuf, 4);
973             datap = A_NETBUF_DATA(osbuf);
974             len = A_NETBUF_LEN(osbuf);
975             bih = (WMI_BSS_INFO_HDR *)datap;
976
977             bih->channel = bih2.channel;
978             bih->frameType = bih2.frameType;
979             bih->snr = bih2.snr;
980             bih->rssi = bih2.snr - 95;
981             bih->ieMask = bih2.ieMask;
982             memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
983
984             status = wmi_bssInfo_event_rx(wmip, datap, len);
985         }
986         break;
987     case (WMI_REGDOMAIN_EVENTID):
988         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
989         status = wmi_regDomain_event_rx(wmip, datap, len);
990         break;
991     case (WMI_PSTREAM_TIMEOUT_EVENTID):
992         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
993         status = wmi_pstream_timeout_event_rx(wmip, datap, len);
994         break;
995     case (WMI_NEIGHBOR_REPORT_EVENTID):
996         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
997         status = wmi_neighborReport_event_rx(wmip, datap, len);
998         break;
999     case (WMI_SCAN_COMPLETE_EVENTID):
1000         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
1001         status = wmi_scanComplete_rx(wmip, datap, len);
1002         break;
1003     case (WMI_CMDERROR_EVENTID):
1004         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
1005         status = wmi_errorEvent_rx(wmip, datap, len);
1006         break;
1007     case (WMI_REPORT_STATISTICS_EVENTID):
1008         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
1009         status = wmi_statsEvent_rx(wmip, datap, len);
1010         break;
1011     case (WMI_RSSI_THRESHOLD_EVENTID):
1012         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
1013         status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
1014         break;
1015     case (WMI_ERROR_REPORT_EVENTID):
1016         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
1017         status = wmi_reportErrorEvent_rx(wmip, datap, len);
1018         break;
1019     case (WMI_OPT_RX_FRAME_EVENTID):
1020         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
1021         status = wmi_opt_frame_event_rx(wmip, datap, len);
1022         break;
1023     case (WMI_REPORT_ROAM_TBL_EVENTID):
1024         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
1025         status = wmi_roam_tbl_event_rx(wmip, datap, len);
1026         break;
1027     case (WMI_EXTENSION_EVENTID):
1028         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
1029         status = wmi_control_rx_xtnd(wmip, osbuf);
1030         break;
1031     case (WMI_CAC_EVENTID):
1032         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
1033         status = wmi_cac_event_rx(wmip, datap, len);
1034         break;
1035     case (WMI_CHANNEL_CHANGE_EVENTID):
1036         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG));
1037         status = wmi_channel_change_event_rx(wmip, datap, len);
1038         break;
1039     case (WMI_REPORT_ROAM_DATA_EVENTID):
1040         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
1041         status = wmi_roam_data_event_rx(wmip, datap, len);
1042         break;
1043 #ifdef CONFIG_HOST_TCMD_SUPPORT
1044     case (WMI_TEST_EVENTID):
1045         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
1046         status = wmi_tcmd_test_report_rx(wmip, datap, len);
1047         break;
1048 #endif
1049     case (WMI_GET_FIXRATES_CMDID):
1050         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
1051         status = wmi_ratemask_reply_rx(wmip, datap, len);
1052         break;
1053     case (WMI_TX_RETRY_ERR_EVENTID):
1054         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
1055         status = wmi_txRetryErrEvent_rx(wmip, datap, len);
1056         break;
1057     case (WMI_SNR_THRESHOLD_EVENTID):
1058         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
1059         status = wmi_snrThresholdEvent_rx(wmip, datap, len);
1060         break;
1061     case (WMI_LQ_THRESHOLD_EVENTID):
1062         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
1063         status = wmi_lqThresholdEvent_rx(wmip, datap, len);
1064         break;
1065     case (WMI_APLIST_EVENTID):
1066         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
1067         status = wmi_aplistEvent_rx(wmip, datap, len);
1068         break;
1069     case (WMI_GET_KEEPALIVE_CMDID):
1070         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
1071         status = wmi_keepalive_reply_rx(wmip, datap, len);
1072         break;
1073     case (WMI_GET_WOW_LIST_EVENTID):
1074         status = wmi_get_wow_list_event_rx(wmip, datap, len);
1075         break;
1076     case (WMI_GET_PMKID_LIST_EVENTID):
1077         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
1078         status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
1079         break;
1080     case (WMI_PSPOLL_EVENTID):
1081         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG));
1082         status = wmi_pspoll_event_rx(wmip, datap, len);
1083         break;
1084     case (WMI_DTIMEXPIRY_EVENTID):
1085         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG));
1086         status = wmi_dtimexpiry_event_rx(wmip, datap, len);
1087         break;
1088     case (WMI_SET_PARAMS_REPLY_EVENTID):
1089         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1090         status = wmi_set_params_event_rx(wmip, datap, len);
1091         break;
1092     case (WMI_ADDBA_REQ_EVENTID):
1093         status = wmi_addba_req_event_rx(wmip, datap, len);
1094         break;
1095     case (WMI_ADDBA_RESP_EVENTID):
1096         status = wmi_addba_resp_event_rx(wmip, datap, len);
1097         break;
1098     case (WMI_DELBA_REQ_EVENTID):
1099         status = wmi_delba_req_event_rx(wmip, datap, len);
1100         break;
1101         case (WMI_REPORT_BTCOEX_CONFIG_EVENTID):
1102             A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG));
1103         status = wmi_btcoex_config_event_rx(wmip, datap, len);
1104             break;
1105         case (WMI_REPORT_BTCOEX_STATS_EVENTID):
1106             A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG));
1107         status = wmi_btcoex_stats_event_rx(wmip, datap, len);
1108             break;
1109     case (WMI_TX_COMPLETE_EVENTID):
1110         {
1111             int index;
1112             TX_COMPLETE_MSG_V1 *pV1;
1113             WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap;
1114             A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType);
1115
1116             for(index = 0 ; index < pEv->numMessages ; index++) {
1117                 pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1));
1118                 A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures);
1119             }
1120         }
1121         break;
1122     case (WMI_HCI_EVENT_EVENTID):
1123         status = wmi_hci_event_rx(wmip, datap, len);
1124         break;
1125 #ifdef WAPI_ENABLE
1126     case (WMI_WAPI_REKEY_EVENTID):
1127         A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG));
1128         status = wmi_wapi_rekey_event_rx(wmip, datap, len);
1129         break;
1130 #endif
1131     default:
1132         A_DPRINTF(DBG_WMI|DBG_ERROR,
1133             (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
1134         wmip->wmi_stats.cmd_id_err++;
1135         status = A_ERROR;
1136         break;
1137     }
1138
1139     A_NETBUF_FREE(osbuf);
1140
1141     return status;
1142 }
1143
1144 /* Send a "simple" wmi command -- one with no arguments */
1145 static int
1146 wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
1147 {
1148     void *osbuf;
1149
1150     osbuf = A_NETBUF_ALLOC(0);
1151     if (osbuf == NULL) {
1152         return A_NO_MEMORY;
1153     }
1154
1155     return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1156 }
1157
1158 /* Send a "simple" extended wmi command -- one with no arguments.
1159    Enabling this command only if GPIO or profiling support is enabled.
1160    This is to suppress warnings on some platforms */
1161 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1162 static int
1163 wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
1164 {
1165     void *osbuf;
1166
1167     osbuf = A_NETBUF_ALLOC(0);
1168     if (osbuf == NULL) {
1169         return A_NO_MEMORY;
1170     }
1171
1172     return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1173 }
1174 #endif
1175
1176 static int
1177 wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1178 {
1179     WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
1180
1181     if (len < sizeof(WMI_READY_EVENT)) {
1182         return A_EINVAL;
1183     }
1184     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1185     wmip->wmi_ready = true;
1186     A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
1187                       ev->sw_version, ev->abi_version);
1188
1189     return 0;
1190 }
1191
1192 #define LE_READ_4(p)                            \
1193     ((u32)                            \
1194      ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
1195       (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
1196
1197 static int __inline
1198 iswmmoui(const u8 *frm)
1199 {
1200     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1201 }
1202
1203 static int __inline
1204 iswmmparam(const u8 *frm)
1205 {
1206     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1207 }
1208
1209
1210 static int
1211 wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1212 {
1213     WMI_CONNECT_EVENT *ev;
1214     u8 *pie,*peie;
1215
1216     if (len < sizeof(WMI_CONNECT_EVENT))
1217     {
1218         return A_EINVAL;
1219     }
1220     ev = (WMI_CONNECT_EVENT *)datap;
1221
1222     A_DPRINTF(DBG_WMI,
1223         (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
1224         DBGARG, ev->channel,
1225         ev->bssid[0], ev->bssid[1], ev->bssid[2],
1226         ev->bssid[3], ev->bssid[4], ev->bssid[5]));
1227
1228     memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
1229
1230     /* initialize pointer to start of assoc rsp IEs */
1231     pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
1232                             sizeof(u16)  +  /* capinfo*/
1233                             sizeof(u16)  +  /* status Code */
1234                             sizeof(u16)  ;  /* associd */
1235
1236     /* initialize pointer to end of assoc rsp IEs */
1237     peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
1238
1239     while (pie < peie)
1240     {
1241         switch (*pie)
1242         {
1243             case IEEE80211_ELEMID_VENDOR:
1244                 if (iswmmoui(pie))
1245                 {
1246                     if(iswmmparam (pie))
1247                     {
1248                         wmip->wmi_is_wmm_enabled = true;
1249                     }
1250                 }
1251             break;
1252         }
1253
1254         if (wmip->wmi_is_wmm_enabled)
1255         {
1256             break;
1257         }
1258         pie += pie[1] + 2;
1259     }
1260
1261     A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
1262                          ev->listenInterval, ev->beaconInterval,
1263                          (NETWORK_TYPE) ev->networkType, ev->beaconIeLen,
1264                          ev->assocReqLen, ev->assocRespLen,
1265                          ev->assocInfo);
1266
1267     return 0;
1268 }
1269
1270 static int
1271 wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1272 {
1273     WMI_REG_DOMAIN_EVENT *ev;
1274
1275     if (len < sizeof(*ev)) {
1276         return A_EINVAL;
1277     }
1278     ev = (WMI_REG_DOMAIN_EVENT *)datap;
1279
1280     A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
1281
1282     return 0;
1283 }
1284
1285 static int
1286 wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1287 {
1288     WMI_NEIGHBOR_REPORT_EVENT *ev;
1289     int numAps;
1290
1291     if (len < sizeof(*ev)) {
1292         return A_EINVAL;
1293     }
1294     ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
1295     numAps = ev->numberOfAps;
1296
1297     if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
1298         return A_EINVAL;
1299     }
1300
1301     A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
1302
1303     return 0;
1304 }
1305
1306 static int
1307 wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1308 {
1309     WMI_DISCONNECT_EVENT *ev;
1310     wmip->wmi_traffic_class = 100;
1311
1312     if (len < sizeof(WMI_DISCONNECT_EVENT)) {
1313         return A_EINVAL;
1314     }
1315     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1316
1317     ev = (WMI_DISCONNECT_EVENT *)datap;
1318
1319     A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
1320
1321     wmip->wmi_is_wmm_enabled = false;
1322     wmip->wmi_pair_crypto_type = NONE_CRYPT;
1323     wmip->wmi_grp_crypto_type = NONE_CRYPT;
1324
1325     A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
1326                             ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
1327
1328     return 0;
1329 }
1330
1331 static int
1332 wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1333 {
1334     WMI_PEER_NODE_EVENT *ev;
1335
1336     if (len < sizeof(WMI_PEER_NODE_EVENT)) {
1337         return A_EINVAL;
1338     }
1339     ev = (WMI_PEER_NODE_EVENT *)datap;
1340     if (ev->eventCode == PEER_NODE_JOIN_EVENT) {
1341         A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG));
1342     } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) {
1343         A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG));
1344     }
1345
1346     A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
1347
1348     return 0;
1349 }
1350
1351 static int
1352 wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1353 {
1354     WMI_TKIP_MICERR_EVENT *ev;
1355
1356     if (len < sizeof(*ev)) {
1357         return A_EINVAL;
1358     }
1359     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1360
1361     ev = (WMI_TKIP_MICERR_EVENT *)datap;
1362     A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
1363
1364     return 0;
1365 }
1366
1367 static int
1368 wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1369 {
1370     bss_t *bss = NULL;
1371     WMI_BSS_INFO_HDR *bih;
1372     u8 *buf;
1373     u32 nodeCachingAllowed = 1;
1374     u8 cached_ssid_len = 0;
1375     u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
1376     u8 beacon_ssid_len = 0;
1377
1378     if (len <= sizeof(WMI_BSS_INFO_HDR)) {
1379         return A_EINVAL;
1380     }
1381
1382     bih = (WMI_BSS_INFO_HDR *)datap;
1383     bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1384
1385     if (bih->rssi > 0) {
1386         if (NULL == bss)
1387             return 0;  //no node found in the table, just drop the node with incorrect RSSI
1388         else
1389             bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
1390     }
1391
1392     A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
1393     /* What is driver config for wlan node caching? */
1394     if(ar6000_get_driver_cfg(wmip->wmi_devt,
1395                     AR6000_DRIVER_CFG_GET_WLANNODECACHING,
1396                     &nodeCachingAllowed) != 0) {
1397         wmi_node_return(wmip, bss);
1398         return A_EINVAL;
1399     }
1400
1401     if(!nodeCachingAllowed) {
1402         wmi_node_return(wmip, bss);
1403         return 0;
1404     }
1405
1406     buf = datap + sizeof(WMI_BSS_INFO_HDR);
1407     len -= sizeof(WMI_BSS_INFO_HDR);
1408
1409         A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
1410                 "bssid \"%pM\"\n", DBGARG, bih->channel,
1411                 (unsigned char) bih->rssi, bih->bssid));
1412
1413     if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
1414         wmi_node_return(wmip, bss);
1415         return 0;
1416     }
1417
1418     if (bss != NULL) {
1419         /*
1420          * Free up the node.  Not the most efficient process given
1421          * we are about to allocate a new node but it is simple and should be
1422          * adequate.
1423          */
1424
1425         /* In case of hidden AP, beacon will not have ssid,
1426          * but a directed probe response will have it,
1427          * so cache the probe-resp-ssid if already present. */
1428         if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
1429         {
1430             u8 *ie_ssid;
1431
1432             ie_ssid = bss->ni_cie.ie_ssid;
1433             if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
1434             {
1435                 cached_ssid_len = ie_ssid[1];
1436                 memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len);
1437             }
1438         }
1439
1440         /*
1441          * Use the current average rssi of associated AP base on assumpiton
1442          * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically
1443          * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...)
1444          * The average value of RSSI give end-user better feeling for instance value of scan result
1445          * It also sync up RSSI info in GUI between scan result and RSSI signal icon
1446          */
1447         if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
1448             bih->rssi = bss->ni_rssi;
1449             bih->snr  = bss->ni_snr;
1450         }
1451
1452         wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1453     }
1454
1455     /*  beacon/probe response frame format
1456      *  [8] time stamp
1457      *  [2] beacon interval
1458      *  [2] capability information
1459      *  [tlv] ssid */
1460     beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
1461
1462     /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
1463     if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1464         (0 != cached_ssid_len) &&
1465         (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1466     {
1467         len += (cached_ssid_len - beacon_ssid_len);
1468     }
1469
1470     bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1471     if (bss == NULL) {
1472         return A_NO_MEMORY;
1473     }
1474
1475     bss->ni_snr        = bih->snr;
1476     bss->ni_rssi       = bih->rssi;
1477     A_ASSERT(bss->ni_buf != NULL);
1478
1479     /* In case of hidden AP, beacon will not have ssid,
1480      * but a directed probe response will have it,
1481      * so place the cached-ssid(probe-resp) in the bssinfo. */
1482     if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1483          (0 != cached_ssid_len) &&
1484          (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1485     {
1486         u8 *ni_buf = bss->ni_buf;
1487         int buf_len = len;
1488
1489         /* copy the first 14 bytes such as
1490          * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
1491         memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
1492
1493         ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
1494         ni_buf += (SSID_IE_LEN_INDEX + 1);
1495
1496         buf += (SSID_IE_LEN_INDEX + 1);
1497         buf_len -= (SSID_IE_LEN_INDEX + 1);
1498
1499         /* copy the cached ssid */
1500         memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
1501         ni_buf += cached_ssid_len;
1502
1503         buf += beacon_ssid_len;
1504         buf_len -= beacon_ssid_len;
1505
1506         if (cached_ssid_len > beacon_ssid_len)
1507             buf_len -= (cached_ssid_len - beacon_ssid_len);
1508
1509         /* now copy the rest of bytes */
1510         memcpy(ni_buf, buf, buf_len);
1511     }
1512     else
1513         memcpy(bss->ni_buf, buf, len);
1514
1515     bss->ni_framelen = len;
1516     if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
1517         wlan_node_free(bss);
1518         return A_EINVAL;
1519     }
1520
1521     /*
1522      * Update the frequency in ie_chan, overwriting of channel number
1523      * which is done in wlan_parse_beacon
1524      */
1525     bss->ni_cie.ie_chan = bih->channel;
1526     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1527
1528     return 0;
1529 }
1530
1531 static int
1532 wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1533 {
1534     bss_t *bss;
1535     WMI_OPT_RX_INFO_HDR *bih;
1536     u8 *buf;
1537
1538     if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
1539         return A_EINVAL;
1540     }
1541
1542     bih = (WMI_OPT_RX_INFO_HDR *)datap;
1543     buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
1544     len -= sizeof(WMI_OPT_RX_INFO_HDR);
1545
1546     A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
1547         bih->bssid[4], bih->bssid[5]));
1548
1549     bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1550     if (bss != NULL) {
1551         /*
1552          * Free up the node.  Not the most efficient process given
1553          * we are about to allocate a new node but it is simple and should be
1554          * adequate.
1555          */
1556         wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1557     }
1558
1559     bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1560     if (bss == NULL) {
1561         return A_NO_MEMORY;
1562     }
1563
1564     bss->ni_snr        = bih->snr;
1565     bss->ni_cie.ie_chan = bih->channel;
1566     A_ASSERT(bss->ni_buf != NULL);
1567     memcpy(bss->ni_buf, buf, len);
1568     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1569
1570     return 0;
1571 }
1572
1573     /* This event indicates inactivity timeout of a fatpipe(pstream)
1574      * at the target
1575      */
1576 static int
1577 wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1578 {
1579     WMI_PSTREAM_TIMEOUT_EVENT *ev;
1580
1581     if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
1582         return A_EINVAL;
1583     }
1584
1585     A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
1586
1587     ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
1588
1589         /* When the pstream (fat pipe == AC) timesout, it means there were no
1590          * thinStreams within this pstream & it got implicitly created due to
1591          * data flow on this AC. We start the inactivity timer only for
1592          * implicitly created pstream. Just reset the host state.
1593      */
1594         /* Set the activeTsids for this AC to 0 */
1595     LOCK_WMI(wmip);
1596     wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
1597     wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
1598     UNLOCK_WMI(wmip);
1599
1600         /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
1601     A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
1602
1603     return 0;
1604 }
1605
1606 static int
1607 wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1608 {
1609     WMI_BIT_RATE_REPLY *reply;
1610     s32 rate;
1611     u32 sgi,index;
1612     /* 54149:
1613      * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
1614      * since there is difference in the length and to avoid returning
1615      * error value.
1616      */
1617     if (len < sizeof(WMI_BIT_RATE_REPLY)) {
1618         return A_EINVAL;
1619     }
1620     reply = (WMI_BIT_RATE_REPLY *)datap;
1621     A_DPRINTF(DBG_WMI,
1622         (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
1623
1624     if (reply->rateIndex == (s8) RATE_AUTO) {
1625         rate = RATE_AUTO;
1626     } else {
1627         // the SGI state is stored as the MSb of the rateIndex
1628         index = reply->rateIndex & 0x7f;
1629         sgi = (reply->rateIndex & 0x80)? 1:0;
1630         rate = wmi_rateTable[index][sgi];
1631     }
1632
1633     A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
1634     return 0;
1635 }
1636
1637 static int
1638 wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1639 {
1640     WMI_FIX_RATES_REPLY *reply;
1641
1642     if (len < sizeof(WMI_FIX_RATES_REPLY)) {
1643         return A_EINVAL;
1644     }
1645     reply = (WMI_FIX_RATES_REPLY *)datap;
1646     A_DPRINTF(DBG_WMI,
1647         (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
1648
1649     A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
1650
1651     return 0;
1652 }
1653
1654 static int
1655 wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1656 {
1657     WMI_CHANNEL_LIST_REPLY *reply;
1658
1659     if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
1660         return A_EINVAL;
1661     }
1662     reply = (WMI_CHANNEL_LIST_REPLY *)datap;
1663     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1664
1665     A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
1666                           reply->channelList);
1667
1668     return 0;
1669 }
1670
1671 static int
1672 wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1673 {
1674     WMI_TX_PWR_REPLY *reply;
1675
1676     if (len < sizeof(*reply)) {
1677         return A_EINVAL;
1678     }
1679     reply = (WMI_TX_PWR_REPLY *)datap;
1680     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1681
1682     A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
1683
1684     return 0;
1685 }
1686 static int
1687 wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1688 {
1689     WMI_GET_KEEPALIVE_CMD *reply;
1690
1691     if (len < sizeof(*reply)) {
1692         return A_EINVAL;
1693     }
1694     reply = (WMI_GET_KEEPALIVE_CMD *)datap;
1695     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1696
1697     A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
1698
1699     return 0;
1700 }
1701
1702
1703 static int
1704 wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1705 {
1706     WMIX_DSETOPENREQ_EVENT *dsetopenreq;
1707
1708     if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
1709         return A_EINVAL;
1710     }
1711     dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
1712     A_DPRINTF(DBG_WMI,
1713         (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
1714     A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
1715                         dsetopenreq->dset_id,
1716                         dsetopenreq->targ_dset_handle,
1717                         dsetopenreq->targ_reply_fn,
1718                         dsetopenreq->targ_reply_arg);
1719
1720     return 0;
1721 }
1722
1723 #ifdef CONFIG_HOST_DSET_SUPPORT
1724 static int
1725 wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
1726 {
1727     WMIX_DSETCLOSE_EVENT *dsetclose;
1728
1729     if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
1730         return A_EINVAL;
1731     }
1732     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1733
1734     dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
1735     A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
1736
1737     return 0;
1738 }
1739
1740 static int
1741 wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1742 {
1743     WMIX_DSETDATAREQ_EVENT *dsetdatareq;
1744
1745     if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
1746         return A_EINVAL;
1747     }
1748     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1749
1750     dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
1751     A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
1752                          dsetdatareq->access_cookie,
1753                          dsetdatareq->offset,
1754                          dsetdatareq->length,
1755                          dsetdatareq->targ_buf,
1756                          dsetdatareq->targ_reply_fn,
1757                          dsetdatareq->targ_reply_arg);
1758
1759     return 0;
1760 }
1761 #endif /* CONFIG_HOST_DSET_SUPPORT */
1762
1763 static int
1764 wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
1765 {
1766     WMI_SCAN_COMPLETE_EVENT *ev;
1767
1768     ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1769     if ((int)ev->status == 0) {
1770         wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1771     }
1772     A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1773     is_probe_ssid = false;
1774
1775     return 0;
1776 }
1777
1778 /*
1779  * Target is reporting a programming error.  This is for
1780  * developer aid only.  Target only checks a few common violations
1781  * and it is responsibility of host to do all error checking.
1782  * Behavior of target after wmi error event is undefined.
1783  * A reset is recommended.
1784  */
1785 static int
1786 wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1787 {
1788     WMI_CMD_ERROR_EVENT *ev;
1789
1790     ev = (WMI_CMD_ERROR_EVENT *)datap;
1791     AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
1792     switch (ev->errorCode) {
1793     case (INVALID_PARAM):
1794         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
1795         break;
1796     case (ILLEGAL_STATE):
1797         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
1798         break;
1799     case (INTERNAL_ERROR):
1800         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
1801         break;
1802     }
1803
1804     return 0;
1805 }
1806
1807
1808 static int
1809 wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1810 {
1811     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1812
1813     A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
1814
1815     return 0;
1816 }
1817
1818 static int
1819 wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1820 {
1821     WMI_RSSI_THRESHOLD_EVENT *reply;
1822     WMI_RSSI_THRESHOLD_VAL newThreshold;
1823     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
1824     SQ_THRESHOLD_PARAMS *sq_thresh =
1825            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
1826     u8 upper_rssi_threshold, lower_rssi_threshold;
1827     s16 rssi;
1828
1829     if (len < sizeof(*reply)) {
1830         return A_EINVAL;
1831     }
1832     reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
1833     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1834     newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range;
1835     rssi = reply->rssi;
1836
1837     /*
1838      * Identify the threshold breached and communicate that to the app. After
1839      * that install a new set of thresholds based on the signal quality
1840      * reported by the target
1841      */
1842     if (newThreshold) {
1843         /* Upper threshold breached */
1844         if (rssi < sq_thresh->upper_threshold[0]) {
1845             A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: "
1846                       " %d\n", DBGARG, rssi));
1847         } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1848                    (rssi >= sq_thresh->upper_threshold[0]))
1849         {
1850             newThreshold = WMI_RSSI_THRESHOLD1_ABOVE;
1851         } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1852                    (rssi >= sq_thresh->upper_threshold[1]))
1853         {
1854             newThreshold = WMI_RSSI_THRESHOLD2_ABOVE;
1855         } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1856                    (rssi >= sq_thresh->upper_threshold[2]))
1857         {
1858             newThreshold = WMI_RSSI_THRESHOLD3_ABOVE;
1859         } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1860                    (rssi >= sq_thresh->upper_threshold[3]))
1861         {
1862             newThreshold = WMI_RSSI_THRESHOLD4_ABOVE;
1863         } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1864                    (rssi >= sq_thresh->upper_threshold[4]))
1865         {
1866             newThreshold = WMI_RSSI_THRESHOLD5_ABOVE;
1867         } else if (rssi >= sq_thresh->upper_threshold[5]) {
1868             newThreshold = WMI_RSSI_THRESHOLD6_ABOVE;
1869         }
1870     } else {
1871         /* Lower threshold breached */
1872         if (rssi > sq_thresh->lower_threshold[0]) {
1873             A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: "
1874                       "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0]));
1875         } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1876                    (rssi <= sq_thresh->lower_threshold[0]))
1877         {
1878             newThreshold = WMI_RSSI_THRESHOLD6_BELOW;
1879         } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1880                    (rssi <= sq_thresh->lower_threshold[1]))
1881         {
1882             newThreshold = WMI_RSSI_THRESHOLD5_BELOW;
1883         } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1884                    (rssi <= sq_thresh->lower_threshold[2]))
1885         {
1886             newThreshold = WMI_RSSI_THRESHOLD4_BELOW;
1887         } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1888                    (rssi <= sq_thresh->lower_threshold[3]))
1889         {
1890             newThreshold = WMI_RSSI_THRESHOLD3_BELOW;
1891         } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1892                    (rssi <= sq_thresh->lower_threshold[4]))
1893         {
1894             newThreshold = WMI_RSSI_THRESHOLD2_BELOW;
1895         } else if (rssi <= sq_thresh->lower_threshold[5]) {
1896             newThreshold = WMI_RSSI_THRESHOLD1_BELOW;
1897         }
1898     }
1899     /* Calculate and install the next set of thresholds */
1900     lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh,
1901                                       sq_thresh->lower_threshold_valid_count);
1902     upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh,
1903                                       sq_thresh->upper_threshold_valid_count);
1904     /* Issue a wmi command to install the thresholds */
1905     cmd.thresholdAbove1_Val = upper_rssi_threshold;
1906     cmd.thresholdBelow1_Val = lower_rssi_threshold;
1907     cmd.weight = sq_thresh->weight;
1908     cmd.pollTime = sq_thresh->polling_interval;
1909
1910     rssi_event_value = rssi;
1911
1912     if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
1913         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
1914                   DBGARG));
1915     }
1916
1917     A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
1918
1919     return 0;
1920 }
1921
1922
1923 static int
1924 wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1925 {
1926     WMI_TARGET_ERROR_REPORT_EVENT *reply;
1927
1928     if (len < sizeof(*reply)) {
1929         return A_EINVAL;
1930     }
1931     reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
1932     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1933
1934     A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
1935
1936     return 0;
1937 }
1938
1939 static int
1940 wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1941 {
1942     WMI_CAC_EVENT *reply;
1943     WMM_TSPEC_IE *tspec_ie;
1944     u16 activeTsids;
1945
1946     if (len < sizeof(*reply)) {
1947         return A_EINVAL;
1948     }
1949     reply = (WMI_CAC_EVENT *)datap;
1950
1951     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1952
1953     if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1954         (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) {
1955         tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1956
1957         wmi_delete_pstream_cmd(wmip, reply->ac,
1958                 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1959     }
1960     else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1961         u8 i;
1962
1963         /* following assumes that there is only one outstanding ADDTS request
1964            when this event is received */
1965         LOCK_WMI(wmip);
1966         activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1967         UNLOCK_WMI(wmip);
1968
1969         for (i = 0; i < sizeof(activeTsids) * 8; i++) {
1970             if ((activeTsids >> i) & 1) {
1971                 break;
1972             }
1973         }
1974         if (i < (sizeof(activeTsids) * 8)) {
1975             wmi_delete_pstream_cmd(wmip, reply->ac, i);
1976         }
1977     }
1978         /*
1979          * Ev#72990: Clear active tsids and Add missing handling
1980          * for delete qos stream from AP
1981          */
1982     else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1983         u8 tsid = 0;
1984
1985         tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1986         tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1987         LOCK_WMI(wmip);
1988         wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid);
1989         activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1990         UNLOCK_WMI(wmip);
1991
1992
1993         /* Indicate stream inactivity to driver layer only if all tsids
1994          * within this AC are deleted.
1995          */
1996        if (!activeTsids) {
1997            A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac);
1998            wmip->wmi_fatPipeExists &= ~(1 << reply->ac);
1999         }
2000     }
2001
2002     A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
2003                 reply->cac_indication, reply->statusCode,
2004                 reply->tspecSuggestion);
2005
2006     return 0;
2007 }
2008
2009 static int
2010 wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2011 {
2012     WMI_CHANNEL_CHANGE_EVENT *reply;
2013
2014     if (len < sizeof(*reply)) {
2015         return A_EINVAL;
2016     }
2017     reply = (WMI_CHANNEL_CHANGE_EVENT *)datap;
2018     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2019
2020     A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
2021                                reply->newChannel);
2022
2023     return 0;
2024 }
2025
2026 static int
2027 wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
2028 {
2029     WMIX_HB_CHALLENGE_RESP_EVENT *reply;
2030
2031     if (len < sizeof(*reply)) {
2032         return A_EINVAL;
2033     }
2034     reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
2035     A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
2036
2037     A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
2038
2039     return 0;
2040 }
2041
2042 static int
2043 wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2044 {
2045     WMI_TARGET_ROAM_TBL *reply;
2046
2047     if (len < sizeof(*reply)) {
2048         return A_EINVAL;
2049     }
2050     reply = (WMI_TARGET_ROAM_TBL *)datap;
2051     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2052
2053     A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
2054
2055     return 0;
2056 }
2057
2058 static int
2059 wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2060 {
2061     WMI_TARGET_ROAM_DATA *reply;
2062
2063     if (len < sizeof(*reply)) {
2064         return A_EINVAL;
2065     }
2066     reply = (WMI_TARGET_ROAM_DATA *)datap;
2067     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2068
2069     A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
2070
2071     return 0;
2072 }
2073
2074 static int
2075 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2076 {
2077     if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
2078         return A_EINVAL;
2079     }
2080     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2081
2082     A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
2083
2084     return 0;
2085 }
2086
2087 static int
2088 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2089 {
2090     WMI_SNR_THRESHOLD_EVENT *reply;
2091     SQ_THRESHOLD_PARAMS *sq_thresh =
2092            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
2093     WMI_SNR_THRESHOLD_VAL newThreshold;
2094     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
2095     u8 upper_snr_threshold, lower_snr_threshold;
2096     s16 snr;
2097
2098     if (len < sizeof(*reply)) {
2099         return A_EINVAL;
2100     }
2101     reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
2102     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2103
2104     newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range;
2105     snr = reply->snr;
2106     /*
2107      * Identify the threshold breached and communicate that to the app. After
2108      * that install a new set of thresholds based on the signal quality
2109      * reported by the target
2110      */
2111     if (newThreshold) {
2112         /* Upper threshold breached */
2113         if (snr < sq_thresh->upper_threshold[0]) {
2114             A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: "
2115                      "%d\n", DBGARG, snr));
2116         } else if ((snr < sq_thresh->upper_threshold[1]) &&
2117                    (snr >= sq_thresh->upper_threshold[0]))
2118         {
2119             newThreshold = WMI_SNR_THRESHOLD1_ABOVE;
2120         } else if ((snr < sq_thresh->upper_threshold[2]) &&
2121                    (snr >= sq_thresh->upper_threshold[1]))
2122         {
2123             newThreshold = WMI_SNR_THRESHOLD2_ABOVE;
2124         } else if ((snr < sq_thresh->upper_threshold[3]) &&
2125                    (snr >= sq_thresh->upper_threshold[2]))
2126         {
2127             newThreshold = WMI_SNR_THRESHOLD3_ABOVE;
2128         } else if (snr >= sq_thresh->upper_threshold[3]) {
2129             newThreshold = WMI_SNR_THRESHOLD4_ABOVE;
2130         }
2131     } else {
2132         /* Lower threshold breached */
2133         if (snr > sq_thresh->lower_threshold[0]) {
2134             A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: "
2135                       "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0]));
2136         } else if ((snr > sq_thresh->lower_threshold[1]) &&
2137                    (snr <= sq_thresh->lower_threshold[0]))
2138         {
2139             newThreshold = WMI_SNR_THRESHOLD4_BELOW;
2140         } else if ((snr > sq_thresh->lower_threshold[2]) &&
2141                    (snr <= sq_thresh->lower_threshold[1]))
2142         {
2143             newThreshold = WMI_SNR_THRESHOLD3_BELOW;
2144         } else if ((snr > sq_thresh->lower_threshold[3]) &&
2145                    (snr <= sq_thresh->lower_threshold[2]))
2146         {
2147             newThreshold = WMI_SNR_THRESHOLD2_BELOW;
2148         } else if (snr <= sq_thresh->lower_threshold[3]) {
2149             newThreshold = WMI_SNR_THRESHOLD1_BELOW;
2150         }
2151     }
2152
2153     /* Calculate and install the next set of thresholds */
2154     lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh,
2155                                       sq_thresh->lower_threshold_valid_count);
2156     upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh,
2157                                       sq_thresh->upper_threshold_valid_count);
2158
2159     /* Issue a wmi command to install the thresholds */
2160     cmd.thresholdAbove1_Val = upper_snr_threshold;
2161     cmd.thresholdBelow1_Val = lower_snr_threshold;
2162     cmd.weight = sq_thresh->weight;
2163     cmd.pollTime = sq_thresh->polling_interval;
2164
2165     A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n"
2166               ,DBGARG, snr, newThreshold, lower_snr_threshold,
2167               upper_snr_threshold));
2168
2169     snr_event_value = snr;
2170
2171     if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
2172         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
2173                   DBGARG));
2174     }
2175     A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
2176
2177     return 0;
2178 }
2179
2180 static int
2181 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2182 {
2183     WMI_LQ_THRESHOLD_EVENT *reply;
2184
2185     if (len < sizeof(*reply)) {
2186         return A_EINVAL;
2187     }
2188     reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
2189     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2190
2191     A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt,
2192                                 (WMI_LQ_THRESHOLD_VAL) reply->range,
2193                                 reply->lq);
2194
2195     return 0;
2196 }
2197
2198 static int
2199 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2200 {
2201     u16 ap_info_entry_size;
2202     WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2203     WMI_AP_INFO_V1 *ap_info_v1;
2204     u8 i;
2205
2206     if (len < sizeof(WMI_APLIST_EVENT)) {
2207         return A_EINVAL;
2208     }
2209
2210     if (ev->apListVer == APLIST_VER1) {
2211         ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
2212         ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
2213     } else {
2214         return A_EINVAL;
2215     }
2216
2217     AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
2218     if (len < (int)(sizeof(WMI_APLIST_EVENT) +
2219               (ev->numAP - 1) * ap_info_entry_size))
2220     {
2221         return A_EINVAL;
2222     }
2223
2224     /*
2225      * AP List Ver1 Contents
2226      */
2227     for (i = 0; i < ev->numAP; i++) {
2228         AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
2229                     "Channel %d\n", i,
2230                    ap_info_v1->bssid[0], ap_info_v1->bssid[1],
2231                    ap_info_v1->bssid[2], ap_info_v1->bssid[3],
2232                    ap_info_v1->bssid[4], ap_info_v1->bssid[5],
2233                    ap_info_v1->channel));
2234         ap_info_v1++;
2235     }
2236     return 0;
2237 }
2238
2239 static int
2240 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2241 {
2242     u32 dropped;
2243
2244     dropped = *((u32 *)datap);
2245     datap += sizeof(dropped);
2246     len -= sizeof(dropped);
2247     A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
2248     return 0;
2249 }
2250
2251 /*
2252  * Called to send a wmi command. Command specific data is already built
2253  * on osbuf and current osbuf->data points to it.
2254  */
2255 int
2256 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2257                WMI_SYNC_FLAG syncflag)
2258 {
2259     int status;
2260 #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
2261     WMI_CMD_HDR         *cHdr;
2262     HTC_ENDPOINT_ID     eid  = wmip->wmi_endpoint_id;
2263
2264     A_ASSERT(osbuf != NULL);
2265
2266     if (syncflag >= END_WMIFLAG) {
2267         A_NETBUF_FREE(osbuf);
2268         return A_EINVAL;
2269     }
2270
2271     if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2272         /*
2273          * We want to make sure all data currently queued is transmitted before
2274          * the cmd execution.  Establish a new sync point.
2275          */
2276         wmi_sync_point(wmip);
2277     }
2278
2279     if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
2280         A_NETBUF_FREE(osbuf);
2281         return A_NO_MEMORY;
2282     }
2283
2284     cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
2285     cHdr->commandId = (u16) cmdId;
2286     cHdr->info1 = 0; // added for virtual interface
2287
2288     /*
2289      * Only for OPT_TX_CMD, use BE endpoint.
2290      */
2291     if (IS_OPT_TX_CMD(cmdId)) {
2292         if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
2293             A_NETBUF_FREE(osbuf);
2294             return status;
2295         }
2296         eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE);
2297     }
2298     A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid);
2299
2300     if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2301         /*
2302          * We want to make sure all new data queued waits for the command to
2303          * execute. Establish a new sync point.
2304          */
2305         wmi_sync_point(wmip);
2306     }
2307     return (0);
2308 #undef IS_OPT_TX_CMD
2309 }
2310
2311 int
2312 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
2313                   WMI_SYNC_FLAG syncflag)
2314 {
2315     WMIX_CMD_HDR     *cHdr;
2316
2317     if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
2318         A_NETBUF_FREE(osbuf);
2319         return A_NO_MEMORY;
2320     }
2321
2322     cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
2323     cHdr->commandId = (u32) cmdId;
2324
2325     return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2326 }
2327
2328 int
2329 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2330                 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
2331                 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2332                 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
2333                 int ssidLength, u8 *ssid,
2334                 u8 *bssid, u16 channel, u32 ctrl_flags)
2335 {
2336     void *osbuf;
2337     WMI_CONNECT_CMD *cc;
2338     wmip->wmi_traffic_class = 100;
2339
2340     if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
2341         return A_EINVAL;
2342     }
2343     if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
2344         return A_EINVAL;
2345     }
2346
2347     osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
2348     if (osbuf == NULL) {
2349         return A_NO_MEMORY;
2350     }
2351
2352     A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
2353
2354     cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2355     A_MEMZERO(cc, sizeof(*cc));
2356
2357     if (ssidLength)
2358     {
2359         memcpy(cc->ssid, ssid, ssidLength);
2360     }
2361
2362     cc->ssidLength          = ssidLength;
2363     cc->networkType         = netType;
2364     cc->dot11AuthMode       = dot11AuthMode;
2365     cc->authMode            = authMode;
2366     cc->pairwiseCryptoType  = pairwiseCrypto;
2367     cc->pairwiseCryptoLen   = pairwiseCryptoLen;
2368     cc->groupCryptoType     = groupCrypto;
2369     cc->groupCryptoLen      = groupCryptoLen;
2370     cc->channel             = channel;
2371     cc->ctrl_flags          = ctrl_flags;
2372
2373     if (bssid != NULL) {
2374         memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2375     }
2376
2377     wmip->wmi_pair_crypto_type  = pairwiseCrypto;
2378     wmip->wmi_grp_crypto_type   = groupCrypto;
2379
2380     return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
2381 }
2382
2383 int
2384 wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
2385 {
2386     void *osbuf;
2387     WMI_RECONNECT_CMD *cc;
2388     wmip->wmi_traffic_class = 100;
2389
2390     osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
2391     if (osbuf == NULL) {
2392         return A_NO_MEMORY;
2393     }
2394
2395     A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
2396
2397     cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2398     A_MEMZERO(cc, sizeof(*cc));
2399
2400     cc->channel = channel;
2401
2402     if (bssid != NULL) {
2403         memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2404     }
2405
2406     return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
2407 }
2408
2409 int
2410 wmi_disconnect_cmd(struct wmi_t *wmip)
2411 {
2412     int status;
2413     wmip->wmi_traffic_class = 100;
2414
2415     /* Bug fix for 24817(elevator bug) - the disconnect command does not
2416        need to do a SYNC before.*/
2417     status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID);
2418
2419     return status;
2420 }
2421
2422 int
2423 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
2424                   u32 forceFgScan, u32 isLegacy,
2425                   u32 homeDwellTime, u32 forceScanInterval,
2426                   s8 numChan, u16 *channelList)
2427 {
2428     void *osbuf;
2429     WMI_START_SCAN_CMD *sc;
2430     s8 size;
2431
2432     size = sizeof (*sc);
2433
2434     if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
2435         return A_EINVAL;
2436     }
2437
2438     if (numChan) {
2439         if (numChan > WMI_MAX_CHANNELS) {
2440             return A_EINVAL;
2441         }
2442         size += sizeof(u16) * (numChan - 1);
2443     }
2444
2445     osbuf = A_NETBUF_ALLOC(size);
2446     if (osbuf == NULL) {
2447         return A_NO_MEMORY;
2448     }
2449
2450     A_NETBUF_PUT(osbuf, size);
2451
2452     sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
2453     sc->scanType = scanType;
2454     sc->forceFgScan = forceFgScan;
2455     sc->isLegacy = isLegacy;
2456     sc->homeDwellTime = homeDwellTime;
2457     sc->forceScanInterval = forceScanInterval;
2458     sc->numChannels = numChan;
2459     if (numChan) {
2460         memcpy(sc->channelList, channelList, numChan * sizeof(u16));
2461     }
2462
2463     return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2464 }
2465
2466 int
2467 wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
2468                    u16 fg_end_sec, u16 bg_sec,
2469                    u16 minact_chdw_msec, u16 maxact_chdw_msec,
2470                    u16 pas_chdw_msec,
2471                    u8 shScanRatio, u8 scanCtrlFlags,
2472                    u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
2473 {
2474     void *osbuf;
2475     WMI_SCAN_PARAMS_CMD *sc;
2476
2477     osbuf = A_NETBUF_ALLOC(sizeof(*sc));
2478     if (osbuf == NULL) {
2479         return A_NO_MEMORY;
2480     }
2481
2482     A_NETBUF_PUT(osbuf, sizeof(*sc));
2483
2484     sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2485     A_MEMZERO(sc, sizeof(*sc));
2486     sc->fg_start_period  = fg_start_sec;
2487     sc->fg_end_period    = fg_end_sec;
2488     sc->bg_period        = bg_sec;
2489     sc->minact_chdwell_time = minact_chdw_msec;
2490     sc->maxact_chdwell_time = maxact_chdw_msec;
2491     sc->pas_chdwell_time = pas_chdw_msec;
2492     sc->shortScanRatio   = shScanRatio;
2493     sc->scanCtrlFlags    = scanCtrlFlags;
2494     sc->max_dfsch_act_time = max_dfsch_act_time;
2495     sc->maxact_scan_per_ssid = maxact_scan_per_ssid;
2496
2497     return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
2498                          NO_SYNC_WMIFLAG));
2499 }
2500
2501 int
2502 wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
2503 {
2504     void *osbuf;
2505     WMI_BSS_FILTER_CMD *cmd;
2506
2507     if (filter >= LAST_BSS_FILTER) {
2508         return A_EINVAL;
2509     }
2510
2511     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2512     if (osbuf == NULL) {
2513         return A_NO_MEMORY;
2514     }
2515
2516     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2517
2518     cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
2519     A_MEMZERO(cmd, sizeof(*cmd));
2520     cmd->bssFilter = filter;
2521     cmd->ieMask = ieMask;
2522
2523     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
2524                          NO_SYNC_WMIFLAG));
2525 }
2526
2527 int
2528 wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
2529                    u8 ssidLength, u8 *ssid)
2530 {
2531     void *osbuf;
2532     WMI_PROBED_SSID_CMD *cmd;
2533
2534     if (index > MAX_PROBED_SSID_INDEX) {
2535         return A_EINVAL;
2536     }
2537     if (ssidLength > sizeof(cmd->ssid)) {
2538         return A_EINVAL;
2539     }
2540     if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
2541         return A_EINVAL;
2542     }
2543     if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
2544         return A_EINVAL;
2545     }
2546
2547     if (flag & SPECIFIC_SSID_FLAG) {
2548         is_probe_ssid = true;
2549     }
2550
2551     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2552     if (osbuf == NULL) {
2553         return A_NO_MEMORY;
2554     }
2555
2556     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2557
2558     cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
2559     A_MEMZERO(cmd, sizeof(*cmd));
2560     cmd->entryIndex = index;
2561     cmd->flag       = flag;
2562     cmd->ssidLength = ssidLength;
2563     memcpy(cmd->ssid, ssid, ssidLength);
2564
2565     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
2566                          NO_SYNC_WMIFLAG));
2567 }
2568
2569 int
2570 wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
2571 {
2572     void *osbuf;
2573     WMI_LISTEN_INT_CMD *cmd;
2574
2575     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2576     if (osbuf == NULL) {
2577         return A_NO_MEMORY;
2578     }
2579
2580     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2581
2582     cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
2583     A_MEMZERO(cmd, sizeof(*cmd));
2584     cmd->listenInterval = listenInterval;
2585     cmd->numBeacons = listenBeacons;
2586
2587     return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
2588                          NO_SYNC_WMIFLAG));
2589 }
2590
2591 int
2592 wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
2593 {
2594     void *osbuf;
2595     WMI_BMISS_TIME_CMD *cmd;
2596
2597     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2598     if (osbuf == NULL) {
2599         return A_NO_MEMORY;
2600     }
2601
2602     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2603
2604     cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
2605     A_MEMZERO(cmd, sizeof(*cmd));
2606     cmd->bmissTime = bmissTime;
2607     cmd->numBeacons =  bmissBeacons;
2608
2609     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
2610                          NO_SYNC_WMIFLAG));
2611 }
2612
2613 int
2614 wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2615                      u8 ieLen, u8 *ieInfo)
2616 {
2617     void *osbuf;
2618     WMI_SET_ASSOC_INFO_CMD *cmd;
2619     u16 cmdLen;
2620
2621     cmdLen = sizeof(*cmd) + ieLen - 1;
2622     osbuf = A_NETBUF_ALLOC(cmdLen);
2623     if (osbuf == NULL) {
2624         return A_NO_MEMORY;
2625     }
2626
2627     A_NETBUF_PUT(osbuf, cmdLen);
2628
2629     cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
2630     A_MEMZERO(cmd, cmdLen);
2631     cmd->ieType = ieType;
2632     cmd->bufferSize = ieLen;
2633     memcpy(cmd->assocInfo, ieInfo, ieLen);
2634
2635     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
2636                          NO_SYNC_WMIFLAG));
2637 }
2638
2639 int
2640 wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
2641 {
2642     void *osbuf;
2643     WMI_POWER_MODE_CMD *cmd;
2644
2645     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2646     if (osbuf == NULL) {
2647         return A_NO_MEMORY;
2648     }
2649
2650     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2651
2652     cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2653     A_MEMZERO(cmd, sizeof(*cmd));
2654     cmd->powerMode = powerMode;
2655     wmip->wmi_powerMode = powerMode;
2656
2657     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
2658                          NO_SYNC_WMIFLAG));
2659 }
2660
2661 int
2662 wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
2663                    u16 atim_windows, u16 timeout_value)
2664 {
2665     void *osbuf;
2666     WMI_IBSS_PM_CAPS_CMD *cmd;
2667
2668     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2669     if (osbuf == NULL) {
2670         return A_NO_MEMORY;
2671     }
2672
2673     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2674
2675     cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
2676     A_MEMZERO(cmd, sizeof(*cmd));
2677     cmd->power_saving = pmEnable;
2678     cmd->ttl = ttl;
2679     cmd->atim_windows = atim_windows;
2680     cmd->timeout_value = timeout_value;
2681
2682     return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
2683                          NO_SYNC_WMIFLAG));
2684 }
2685
2686 int
2687 wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2688                    u32 ps_period, u8 sleep_period)
2689 {
2690     void *osbuf;
2691     WMI_AP_PS_CMD *cmd;
2692
2693     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2694     if (osbuf == NULL) {
2695         return A_NO_MEMORY;
2696     }
2697
2698     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2699
2700     cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf));
2701     A_MEMZERO(cmd, sizeof(*cmd));
2702     cmd->psType = psType;
2703     cmd->idle_time = idle_time;
2704     cmd->ps_period = ps_period;
2705     cmd->sleep_period = sleep_period;
2706
2707     return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID,
2708                          NO_SYNC_WMIFLAG));
2709 }
2710
2711 int
2712 wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
2713                  u16 psPollNum, u16 dtimPolicy,
2714                  u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2715                  u16 ps_fail_event_policy)
2716 {
2717     void *osbuf;
2718     WMI_POWER_PARAMS_CMD *pm;
2719
2720     osbuf = A_NETBUF_ALLOC(sizeof(*pm));
2721     if (osbuf == NULL) {
2722         return A_NO_MEMORY;
2723     }
2724
2725     A_NETBUF_PUT(osbuf, sizeof(*pm));
2726
2727     pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2728     A_MEMZERO(pm, sizeof(*pm));
2729     pm->idle_period   = idlePeriod;
2730     pm->pspoll_number = psPollNum;
2731     pm->dtim_policy   = dtimPolicy;
2732     pm->tx_wakeup_policy = tx_wakeup_policy;
2733     pm->num_tx_to_wakeup = num_tx_to_wakeup;
2734     pm->ps_fail_event_policy = ps_fail_event_policy;
2735
2736     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
2737                          NO_SYNC_WMIFLAG));
2738 }
2739
2740 int
2741 wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
2742 {
2743     void *osbuf;
2744     WMI_DISC_TIMEOUT_CMD *cmd;
2745
2746     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2747     if (osbuf == NULL) {
2748         return A_NO_MEMORY;
2749     }
2750
2751     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2752
2753     cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
2754     A_MEMZERO(cmd, sizeof(*cmd));
2755     cmd->disconnectTimeout = timeout;
2756
2757     return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
2758                          NO_SYNC_WMIFLAG));
2759 }
2760
2761 int
2762 wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
2763                u8 keyUsage, u8 keyLength, u8 *keyRSC,
2764                u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
2765                WMI_SYNC_FLAG sync_flag)
2766 {
2767     void *osbuf;
2768     WMI_ADD_CIPHER_KEY_CMD *cmd;
2769
2770     if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
2771         (keyMaterial == NULL))
2772     {
2773         return A_EINVAL;
2774     }
2775
2776     if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
2777         return A_EINVAL;
2778     }
2779
2780     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2781     if (osbuf == NULL) {
2782         return A_NO_MEMORY;
2783     }
2784
2785     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2786
2787     cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2788     A_MEMZERO(cmd, sizeof(*cmd));
2789     cmd->keyIndex = keyIndex;
2790     cmd->keyType  = keyType;
2791     cmd->keyUsage = keyUsage;
2792     cmd->keyLength = keyLength;
2793     memcpy(cmd->key, keyMaterial, keyLength);
2794 #ifdef WAPI_ENABLE
2795     if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
2796 #else
2797     if (NULL != keyRSC) {
2798 #endif // WAPI_ENABLE
2799         memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
2800     }
2801     cmd->key_op_ctrl = key_op_ctrl;
2802
2803     if(macAddr) {
2804         memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
2805     }
2806
2807     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
2808 }
2809
2810 int
2811 wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
2812 {
2813     void *osbuf;
2814     WMI_ADD_KRK_CMD *cmd;
2815
2816     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2817     if (osbuf == NULL) {
2818         return A_NO_MEMORY;
2819     }
2820
2821     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2822
2823     cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
2824     A_MEMZERO(cmd, sizeof(*cmd));
2825     memcpy(cmd->krk, krk, WMI_KRK_LEN);
2826
2827     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
2828 }
2829
2830 int
2831 wmi_delete_krk_cmd(struct wmi_t *wmip)
2832 {
2833     return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2834 }
2835
2836 int
2837 wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
2838 {
2839     void *osbuf;
2840     WMI_DELETE_CIPHER_KEY_CMD *cmd;
2841
2842     if (keyIndex > WMI_MAX_KEY_INDEX) {
2843         return A_EINVAL;
2844     }
2845
2846     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2847     if (osbuf == NULL) {
2848         return A_NO_MEMORY;
2849     }
2850
2851     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2852
2853     cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2854     A_MEMZERO(cmd, sizeof(*cmd));
2855     cmd->keyIndex = keyIndex;
2856
2857     return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
2858                          NO_SYNC_WMIFLAG));
2859 }
2860
2861 int
2862 wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
2863                  bool set)
2864 {
2865     void *osbuf;
2866     WMI_SET_PMKID_CMD *cmd;
2867
2868     if (bssid == NULL) {
2869         return A_EINVAL;
2870     }
2871
2872     if ((set == true) && (pmkId == NULL)) {
2873         return A_EINVAL;
2874     }
2875
2876     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2877     if (osbuf == NULL) {
2878         return A_NO_MEMORY;
2879     }
2880
2881     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2882
2883     cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
2884     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
2885     if (set == true) {
2886         memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
2887         cmd->enable = PMKID_ENABLE;
2888     } else {
2889         A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
2890         cmd->enable = PMKID_DISABLE;
2891     }
2892
2893     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
2894 }
2895
2896 int
2897 wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
2898 {
2899     void *osbuf;
2900     WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
2901
2902     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2903     if (osbuf == NULL) {
2904         return A_NO_MEMORY;
2905     }
2906
2907     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2908
2909     cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
2910     cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
2911
2912     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
2913             NO_SYNC_WMIFLAG));
2914 }
2915
2916 int
2917 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
2918                         WMI_SET_AKMP_PARAMS_CMD *akmpParams)
2919 {
2920     void *osbuf;
2921     WMI_SET_AKMP_PARAMS_CMD *cmd;
2922
2923     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2924     if (osbuf == NULL) {
2925         return A_NO_MEMORY;
2926     }
2927
2928     A_NETBUF_PUT(osbuf, sizeof(*cmd));
2929     cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2930     cmd->akmpInfo = akmpParams->akmpInfo;
2931
2932     return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
2933             NO_SYNC_WMIFLAG));
2934 }
2935
2936 int
2937 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
2938                        WMI_SET_PMKID_LIST_CMD *pmkInfo)
2939 {
2940     void *osbuf;
2941     WMI_SET_PMKID_LIST_CMD *cmd;
2942     u16 cmdLen;
2943     u8 i;
2944
2945     cmdLen = sizeof(pmkInfo->numPMKID) +
2946              pmkInfo->numPMKID * sizeof(WMI_PMKID);
2947
2948     osbuf = A_NETBUF_ALLOC(cmdLen);
2949     if (osbuf == NULL) {
2950         return A_NO_MEMORY;
2951     }
2952
2953     A_NETBUF_PUT(osbuf, cmdLen);
2954     cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2955     cmd->numPMKID = pmkInfo->numPMKID;
2956
2957     for (i = 0; i < cmd->numPMKID; i++) {
2958         memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
2959                  WMI_PMKID_LEN);
2960     }
2961
2962     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
2963             NO_SYNC_WMIFLAG));
2964 }
2965
2966 int
2967 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
2968 {
2969     return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
2970 }
2971
2972 int
2973 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
2974 {
2975     WMI_DATA_HDR     *dtHdr;
2976
2977     A_ASSERT( eid != wmip->wmi_endpoint_id);
2978     A_ASSERT(osbuf != NULL);
2979
2980     if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
2981         return A_NO_MEMORY;
2982     }
2983
2984     dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
2985     dtHdr->info =
2986       (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
2987
2988     dtHdr->info3 = 0;
2989     A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid));
2990
2991     return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid));
2992 }
2993
2994 typedef struct _WMI_DATA_SYNC_BUFS {
2995     u8 trafficClass;
2996     void               *osbuf;
2997 }WMI_DATA_SYNC_BUFS;
2998
2999 static int
3000 wmi_sync_point(struct wmi_t *wmip)
3001 {
3002     void *cmd_osbuf;
3003     WMI_SYNC_CMD *cmd;
3004     WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
3005     u8 i,numPriStreams=0;
3006     int status = 0;
3007
3008     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3009
3010     memset(dataSyncBufs,0,sizeof(dataSyncBufs));
3011
3012     /* lock out while we walk through the priority list and assemble our local array */
3013     LOCK_WMI(wmip);
3014
3015     for (i=0; i < WMM_NUM_AC ; i++) {
3016         if (wmip->wmi_fatPipeExists & (1 << i)) {
3017             numPriStreams++;
3018             dataSyncBufs[numPriStreams-1].trafficClass = i;
3019         }
3020     }
3021
3022     UNLOCK_WMI(wmip);
3023
3024     /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
3025
3026     do {
3027         /*
3028          * We allocate all network buffers needed so we will be able to
3029          * send all required frames.
3030          */
3031         cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3032         if (cmd_osbuf == NULL) {
3033             status = A_NO_MEMORY;
3034             break;
3035     }
3036
3037         A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd));
3038
3039         cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf));
3040         A_MEMZERO(cmd, sizeof(*cmd));
3041
3042         /* In the SYNC cmd sent on the control Ep, send a bitmap of the data
3043          * eps on which the Data Sync will be sent
3044          */
3045         cmd->dataSyncMap = wmip->wmi_fatPipeExists;
3046
3047         for (i=0; i < numPriStreams ; i++) {
3048             dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
3049             if (dataSyncBufs[i].osbuf == NULL) {
3050                 status = A_NO_MEMORY;
3051                 break;
3052             }
3053         } //end for
3054
3055         /* if Buffer allocation for any of the dataSync fails, then do not
3056          * send the Synchronize cmd on the control ep
3057          */
3058         if (status) {
3059             break;
3060         }
3061
3062     /*
3063      * Send sync cmd followed by sync data messages on all endpoints being
3064      * used
3065      */
3066     status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
3067                           NO_SYNC_WMIFLAG);
3068
3069         if (status) {
3070             break;
3071     }
3072             /* cmd buffer sent, we no longer own it */
3073         cmd_osbuf = NULL;
3074
3075         for(i=0; i < numPriStreams; i++) {
3076             A_ASSERT(dataSyncBufs[i].osbuf != NULL);
3077             status = wmi_dataSync_send(wmip,
3078                                        dataSyncBufs[i].osbuf,
3079                                        A_WMI_Ac2EndpointID(wmip->wmi_devt,
3080                                                             dataSyncBufs[i].
3081                                                             trafficClass)
3082                                       );
3083
3084             if (status) {
3085                 break;
3086             }
3087             /* we don't own this buffer anymore, NULL it out of the array so it
3088              * won't get cleaned up */
3089             dataSyncBufs[i].osbuf = NULL;
3090         } //end for
3091
3092     } while(false);
3093
3094     /* free up any resources left over (possibly due to an error) */
3095
3096     if (cmd_osbuf != NULL) {
3097         A_NETBUF_FREE(cmd_osbuf);
3098             }
3099
3100     for (i = 0; i < numPriStreams; i++) {
3101         if (dataSyncBufs[i].osbuf != NULL) {
3102             A_NETBUF_FREE(dataSyncBufs[i].osbuf);
3103         }
3104     }
3105
3106     return (status);
3107 }
3108
3109 int
3110 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
3111 {
3112     void *osbuf;
3113     WMI_CREATE_PSTREAM_CMD *cmd;
3114     u8 fatPipeExistsForAC=0;
3115     s32 minimalPHY = 0;
3116     s32 nominalPHY = 0;
3117
3118     /* Validate all the parameters. */
3119     if( !((params->userPriority < 8) &&
3120          (params->userPriority <= 0x7) &&
3121          (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass)  &&
3122          (params->trafficDirection == UPLINK_TRAFFIC ||
3123             params->trafficDirection == DNLINK_TRAFFIC ||
3124             params->trafficDirection == BIDIR_TRAFFIC) &&
3125          (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
3126             params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
3127          (params->voicePSCapability == DISABLE_FOR_THIS_AC  ||
3128             params->voicePSCapability == ENABLE_FOR_THIS_AC ||
3129             params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
3130          (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
3131     {
3132         return  A_EINVAL;
3133     }
3134
3135     //
3136     // check nominal PHY rate is >= minimalPHY, so that DUT
3137     // can allow TSRS IE
3138     //
3139
3140     // get the physical rate
3141     minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps
3142
3143     // check minimal phy < nominal phy rate
3144     //
3145     if (params->nominalPHY >= minimalPHY)
3146     {
3147         nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps
3148         A_DPRINTF(DBG_WMI,
3149                   (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG,
3150                   minimalPHY, nominalPHY));
3151
3152         params->nominalPHY = nominalPHY;
3153     }
3154     else
3155     {
3156         params->nominalPHY = 0;
3157     }
3158
3159     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3160     if (osbuf == NULL) {
3161         return A_NO_MEMORY;
3162     }
3163
3164     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3165
3166     A_DPRINTF(DBG_WMI,
3167         (DBGFMT "Sending create_pstream_cmd: ac=%d    tsid:%d\n", DBGARG,
3168         params->trafficClass, params->tsid));
3169
3170     cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3171     A_MEMZERO(cmd, sizeof(*cmd));
3172     memcpy(cmd, params, sizeof(*cmd));
3173
3174         /* this is an implicitly created Fat pipe */
3175     if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
3176         LOCK_WMI(wmip);
3177         fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3178         wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3179         UNLOCK_WMI(wmip);
3180     } else {
3181             /* this is an explicitly created thin stream within a fat pipe */
3182     LOCK_WMI(wmip);
3183         fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3184     wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
3185             /* if a thinstream becomes active, the fat pipe automatically
3186             * becomes active
3187             */
3188         wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3189     UNLOCK_WMI(wmip);
3190     }
3191
3192         /* Indicate activty change to driver layer only if this is the
3193          * first TSID to get created in this AC explicitly or an implicit
3194          * fat pipe is getting created.
3195          */
3196     if (!fatPipeExistsForAC) {
3197         A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
3198     }
3199
3200     /* mike: should be SYNC_BEFORE_WMIFLAG */
3201     return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
3202                          NO_SYNC_WMIFLAG));
3203 }
3204
3205 int
3206 wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
3207 {
3208     void *osbuf;
3209     WMI_DELETE_PSTREAM_CMD *cmd;
3210     int status;
3211     u16 activeTsids=0;
3212
3213     /* validate the parameters */
3214     if (trafficClass > 3) {
3215         A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass));
3216         return A_EINVAL;
3217     }
3218
3219     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3220     if (osbuf == NULL) {
3221         return A_NO_MEMORY;
3222     }
3223
3224     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3225
3226     cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3227     A_MEMZERO(cmd, sizeof(*cmd));
3228
3229     cmd->trafficClass = trafficClass;
3230     cmd->tsid = tsid;
3231
3232     LOCK_WMI(wmip);
3233     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3234     UNLOCK_WMI(wmip);
3235
3236         /* Check if the tsid was created & exists */
3237     if (!(activeTsids & (1<<tsid))) {
3238
3239         A_NETBUF_FREE(osbuf);
3240         A_DPRINTF(DBG_WMI,
3241         (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
3242             /* TODO: return a more appropriate err code */
3243         return A_ERROR;
3244     }
3245
3246     A_DPRINTF(DBG_WMI,
3247         (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
3248
3249     status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
3250                          SYNC_BEFORE_WMIFLAG));
3251
3252     LOCK_WMI(wmip);
3253     wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
3254     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3255     UNLOCK_WMI(wmip);
3256
3257
3258         /* Indicate stream inactivity to driver layer only if all tsids
3259          * within this AC are deleted.
3260          */
3261     if(!activeTsids) {
3262         A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
3263         wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
3264     }
3265
3266     return status;
3267 }
3268
3269 int
3270 wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
3271 {
3272     void *osbuf;
3273     WMI_FRAME_RATES_CMD *cmd;
3274     u8 frameType;
3275
3276     A_DPRINTF(DBG_WMI,
3277         (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
3278
3279     if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) ||
3280         (subType > 15)){
3281
3282         return A_EINVAL;
3283     }
3284
3285     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3286     if (osbuf == NULL) {
3287         return A_NO_MEMORY;
3288     }
3289
3290     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3291
3292     cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3293     A_MEMZERO(cmd, sizeof(*cmd));
3294
3295     frameType = (u8)((subType << 4) | type);
3296
3297     cmd->bEnableMask = bEnable;
3298     cmd->frameType = frameType;
3299     cmd->frameRateMask = rateMask;
3300
3301     return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG));
3302 }
3303
3304 /*
3305  * used to set the bit rate.  rate is in Kbps.  If rate == -1
3306  * then auto selection is used.
3307  */
3308 int
3309 wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
3310 {
3311     void *osbuf;
3312     WMI_BIT_RATE_CMD *cmd;
3313     s8 drix, mrix, crix, ret_val;
3314
3315     if (dataRate != -1) {
3316         ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
3317         if(ret_val == A_EINVAL){
3318             return A_EINVAL;
3319         }
3320     } else {
3321         drix = -1;
3322     }
3323
3324     if (mgmtRate != -1) {
3325         ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix);
3326         if(ret_val == A_EINVAL){
3327             return A_EINVAL;
3328         }
3329     } else {
3330         mrix = -1;
3331     }
3332     if (ctlRate != -1) {
3333         ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix);
3334         if(ret_val == A_EINVAL){
3335             return A_EINVAL;
3336         }
3337     } else {
3338         crix = -1;
3339     }
3340     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3341     if (osbuf == NULL) {
3342         return A_NO_MEMORY;
3343     }
3344
3345     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3346
3347     cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
3348     A_MEMZERO(cmd, sizeof(*cmd));
3349
3350     cmd->rateIndex = drix;
3351     cmd->mgmtRateIndex = mrix;
3352     cmd->ctlRateIndex  = crix;
3353
3354
3355     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
3356 }
3357
3358 int
3359 wmi_get_bitrate_cmd(struct wmi_t *wmip)
3360 {
3361     return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
3362 }
3363
3364 /*
3365  * Returns true iff the given rate index is legal in the current PHY mode.
3366  */
3367 bool
3368 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
3369 {
3370     WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
3371     bool isValid = true;
3372     switch(phyMode) {
3373         case WMI_11A_MODE:
3374             if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
3375                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3376                     isValid = false;
3377                 }
3378             } else {
3379                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
3380                     isValid = false;
3381                 }
3382             }
3383             break;
3384
3385         case WMI_11B_MODE:
3386             if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
3387                 isValid = false;
3388             }
3389             break;
3390
3391         case WMI_11GONLY_MODE:
3392             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3393                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3394                     isValid = false;
3395                 }
3396             } else {
3397                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
3398                     isValid = false;
3399                 }
3400             }
3401             break;
3402
3403         case WMI_11G_MODE:
3404         case WMI_11AG_MODE:
3405             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3406                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3407                     isValid = false;
3408                 }
3409             } else {
3410                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
3411                     isValid = false;
3412                 }
3413             }
3414             break;
3415         default:
3416             A_ASSERT(false);
3417             break;
3418     }
3419
3420     return isValid;
3421 }
3422
3423 s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
3424 {
3425     s8 i;
3426
3427     for (i=0;;i++)
3428     {
3429         if (wmi_rateTable[(u32) i][0] == 0) {
3430             return A_EINVAL;
3431         }
3432         if (wmi_rateTable[(u32) i][0] == rate) {
3433             break;
3434         }
3435     }
3436
3437     if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
3438         return A_EINVAL;
3439     }
3440
3441     *rate_idx = i;
3442     return 0;
3443 }
3444
3445 int
3446 wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
3447 {
3448     void *osbuf;
3449     WMI_FIX_RATES_CMD *cmd;
3450 #if 0
3451     s32 rateIndex;
3452 /* This check does not work for AR6003 as the HT modes are enabled only when
3453  * the STA is connected to a HT_BSS and is not based only on channel. It is
3454  * safe to skip this check however because rate control will only use rates
3455  * that are permitted by the valid rate mask and the fix rate mask. Meaning
3456  * the fix rate mask is not sufficient by itself to cause an invalid rate
3457  * to be used. */
3458     /* Make sure all rates in the mask are valid in the current PHY mode */
3459     for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
3460        if((1 << rateIndex) & (u32)fixRatesMask) {
3461             if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
3462                 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
3463                 return A_EINVAL;
3464             }
3465        }
3466     }
3467 #endif
3468
3469
3470     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3471     if (osbuf == NULL) {
3472         return A_NO_MEMORY;
3473     }
3474
3475     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3476
3477     cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3478     A_MEMZERO(cmd, sizeof(*cmd));
3479
3480     cmd->fixRateMask = fixRatesMask;
3481
3482     return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
3483 }
3484
3485 int
3486 wmi_get_ratemask_cmd(struct wmi_t *wmip)
3487 {
3488     return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3489 }
3490
3491 int
3492 wmi_get_channelList_cmd(struct wmi_t *wmip)
3493 {
3494     return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
3495 }
3496
3497 /*
3498  * used to generate a wmi sey channel Parameters cmd.
3499  * mode should always be specified and corresponds to the phy mode of the
3500  * wlan.
3501  * numChan should alway sbe specified. If zero indicates that all available
3502  * channels should be used.
3503  * channelList is an array of channel frequencies (in Mhz) which the radio
3504  * should limit its operation to.  It should be NULL if numChan == 0.  Size of
3505  * array should correspond to numChan entries.
3506  */
3507 int
3508 wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
3509                           WMI_PHY_MODE mode, s8 numChan,
3510                           u16 *channelList)
3511 {
3512     void *osbuf;
3513     WMI_CHANNEL_PARAMS_CMD *cmd;
3514     s8 size;
3515
3516     size = sizeof (*cmd);
3517
3518     if (numChan) {
3519         if (numChan > WMI_MAX_CHANNELS) {
3520             return A_EINVAL;
3521         }
3522         size += sizeof(u16) * (numChan - 1);
3523     }
3524
3525     osbuf = A_NETBUF_ALLOC(size);
3526     if (osbuf == NULL) {
3527         return A_NO_MEMORY;
3528     }
3529
3530     A_NETBUF_PUT(osbuf, size);
3531
3532     cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3533     A_MEMZERO(cmd, size);
3534
3535     wmip->wmi_phyMode = mode;
3536     cmd->scanParam   = scanParam;
3537     cmd->phyMode     = mode;
3538     cmd->numChannels = numChan;
3539     memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
3540
3541     return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3542                          NO_SYNC_WMIFLAG));
3543 }
3544
3545 void
3546 wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3547 {
3548     SQ_THRESHOLD_PARAMS *sq_thresh =
3549            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
3550     /*
3551      * Parse the command and store the threshold values here. The checks
3552      * for valid values can be put here
3553      */
3554     sq_thresh->weight = rssiCmd->weight;
3555     sq_thresh->polling_interval = rssiCmd->pollTime;
3556
3557     sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3558     sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3559     sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3560     sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3561     sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3562     sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3563     sq_thresh->upper_threshold_valid_count = 6;
3564
3565     /* List sorted in descending order */
3566     sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3567     sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3568     sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3569     sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3570     sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3571     sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3572     sq_thresh->lower_threshold_valid_count = 6;
3573
3574     if (!rssi_event_value) {
3575     /*
3576      * Configuring the thresholds to their extremes allows the host to get an
3577      * event from the target which is used for the configuring the correct
3578      * thresholds
3579      */
3580     rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
3581     rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
3582     } else {
3583         /*
3584          * In case the user issues multiple times of rssi_threshold_setting,
3585          * we should not use the extreames anymore, the target does not expect that.
3586          */
3587         rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
3588                                               sq_thresh->upper_threshold_valid_count);
3589         rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
3590                                               sq_thresh->lower_threshold_valid_count);
3591 }
3592 }
3593
3594 int
3595 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
3596                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3597 {
3598
3599      /* Check these values are in ascending order */
3600     if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
3601         rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
3602         rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
3603         rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
3604         rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
3605         rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
3606         rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
3607         rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
3608         rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
3609         rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
3610     {
3611         return A_EINVAL;
3612     }
3613
3614     wmi_cache_configure_rssithreshold(wmip, rssiCmd);
3615
3616     return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
3617 }
3618
3619 int
3620 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
3621 {
3622     void    *osbuf;
3623     WMI_SET_IP_CMD *cmd;
3624
3625     /* Multicast address are not valid */
3626     if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3627        (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
3628         return A_EINVAL;
3629     }
3630
3631     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
3632     if (osbuf == NULL) {
3633         return A_NO_MEMORY;
3634     }
3635
3636     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
3637     cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
3638     memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
3639
3640     return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3641                             NO_SYNC_WMIFLAG));
3642 }
3643
3644 int
3645 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3646                               WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3647 {
3648     void    *osbuf;
3649     s8 size;
3650     WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
3651     u16 activeTsids=0;
3652     u8 streamExists=0;
3653     u8 i;
3654
3655     if( hostModeCmd->awake == hostModeCmd->asleep) {
3656         return A_EINVAL;
3657     }
3658
3659     size = sizeof (*cmd);
3660
3661     osbuf = A_NETBUF_ALLOC(size);
3662     if (osbuf == NULL) {
3663         return A_NO_MEMORY;
3664     }
3665
3666     A_NETBUF_PUT(osbuf, size);
3667
3668     cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3669     A_MEMZERO(cmd, size);
3670     memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
3671
3672     if(hostModeCmd->asleep) {
3673         /*
3674          * Relinquish credits from all implicitly created pstreams since when we
3675          * go to sleep. If user created explicit thinstreams exists with in a
3676          * fatpipe leave them intact for the user to delete
3677          */
3678         LOCK_WMI(wmip);
3679         streamExists = wmip->wmi_fatPipeExists;
3680         UNLOCK_WMI(wmip);
3681
3682         for(i=0;i< WMM_NUM_AC;i++) {
3683             if (streamExists & (1<<i)) {
3684                 LOCK_WMI(wmip);
3685                 activeTsids = wmip->wmi_streamExistsForAC[i];
3686                 UNLOCK_WMI(wmip);
3687                 /* If there are no user created thin streams delete the fatpipe */
3688                 if(!activeTsids) {
3689                     streamExists &= ~(1<<i);
3690                     /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
3691                     A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
3692                 }
3693             }
3694         }
3695
3696         /* Update the fatpipes that exists*/
3697         LOCK_WMI(wmip);
3698         wmip->wmi_fatPipeExists = streamExists;
3699         UNLOCK_WMI(wmip);
3700     }
3701
3702     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
3703                             NO_SYNC_WMIFLAG));
3704 }
3705
3706 int
3707 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3708                               WMI_SET_WOW_MODE_CMD *wowModeCmd)
3709 {
3710     void    *osbuf;
3711     s8 size;
3712     WMI_SET_WOW_MODE_CMD *cmd;
3713
3714     size = sizeof (*cmd);
3715
3716     osbuf = A_NETBUF_ALLOC(size);
3717     if (osbuf == NULL) {
3718         return A_NO_MEMORY;
3719     }
3720
3721     A_NETBUF_PUT(osbuf, size);
3722
3723     cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3724     A_MEMZERO(cmd, size);
3725     memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
3726
3727     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3728                             NO_SYNC_WMIFLAG));
3729
3730 }
3731
3732 int
3733 wmi_get_wow_list_cmd(struct wmi_t *wmip,
3734                               WMI_GET_WOW_LIST_CMD *wowListCmd)
3735 {
3736     void    *osbuf;
3737     s8 size;
3738     WMI_GET_WOW_LIST_CMD *cmd;
3739
3740     size = sizeof (*cmd);
3741
3742     osbuf = A_NETBUF_ALLOC(size);
3743     if (osbuf == NULL) {
3744         return A_NO_MEMORY;
3745     }
3746
3747     A_NETBUF_PUT(osbuf, size);
3748
3749     cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
3750     A_MEMZERO(cmd, size);
3751     memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
3752
3753     return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3754                             NO_SYNC_WMIFLAG));
3755
3756 }
3757
3758 static int
3759 wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
3760 {
3761     WMI_GET_WOW_LIST_REPLY *reply;
3762
3763     if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
3764         return A_EINVAL;
3765     }
3766     reply = (WMI_GET_WOW_LIST_REPLY *)datap;
3767
3768     A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
3769                           reply);
3770
3771     return 0;
3772 }
3773
3774 int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
3775                                  WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
3776                                  u8 *pattern, u8 *mask,
3777                                  u8 pattern_size)
3778 {
3779     void    *osbuf;
3780     s8 size;
3781     WMI_ADD_WOW_PATTERN_CMD *cmd;
3782     u8 *filter_mask = NULL;
3783
3784     size = sizeof (*cmd);
3785
3786     size += ((2 * addWowCmd->filter_size)* sizeof(u8));
3787     osbuf = A_NETBUF_ALLOC(size);
3788     if (osbuf == NULL) {
3789         return A_NO_MEMORY;
3790     }
3791
3792     A_NETBUF_PUT(osbuf, size);
3793
3794     cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3795     cmd->filter_list_id = addWowCmd->filter_list_id;
3796     cmd->filter_offset = addWowCmd->filter_offset;
3797     cmd->filter_size = addWowCmd->filter_size;
3798
3799     memcpy(cmd->filter, pattern, addWowCmd->filter_size);
3800
3801     filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
3802     memcpy(filter_mask, mask, addWowCmd->filter_size);
3803
3804
3805     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3806                             NO_SYNC_WMIFLAG));
3807 }
3808
3809 int
3810 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3811                               WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3812 {
3813     void    *osbuf;
3814     s8 size;
3815     WMI_DEL_WOW_PATTERN_CMD *cmd;
3816
3817     size = sizeof (*cmd);
3818
3819     osbuf = A_NETBUF_ALLOC(size);
3820     if (osbuf == NULL) {
3821         return A_NO_MEMORY;
3822     }
3823
3824     A_NETBUF_PUT(osbuf, size);
3825
3826     cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3827     A_MEMZERO(cmd, size);
3828     memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
3829
3830     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3831                             NO_SYNC_WMIFLAG));
3832
3833 }
3834
3835 void
3836 wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3837 {
3838     SQ_THRESHOLD_PARAMS *sq_thresh =
3839            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
3840     /*
3841      * Parse the command and store the threshold values here. The checks
3842      * for valid values can be put here
3843      */
3844     sq_thresh->weight = snrCmd->weight;
3845     sq_thresh->polling_interval = snrCmd->pollTime;
3846
3847     sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
3848     sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
3849     sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
3850     sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
3851     sq_thresh->upper_threshold_valid_count = 4;
3852
3853     /* List sorted in descending order */
3854     sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
3855     sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
3856     sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
3857     sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
3858     sq_thresh->lower_threshold_valid_count = 4;
3859
3860     if (!snr_event_value) {
3861     /*
3862      * Configuring the thresholds to their extremes allows the host to get an
3863      * event from the target which is used for the configuring the correct
3864      * thresholds
3865      */
3866     snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3867     snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
3868     } else {
3869         /*
3870          * In case the user issues multiple times of snr_threshold_setting,
3871          * we should not use the extreames anymore, the target does not expect that.
3872          */
3873         snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
3874                                               sq_thresh->upper_threshold_valid_count);
3875         snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
3876                                               sq_thresh->lower_threshold_valid_count);
3877     }
3878
3879 }
3880 int
3881 wmi_set_snr_threshold_params(struct wmi_t *wmip,
3882                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3883 {
3884     if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
3885         snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
3886         snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
3887         snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
3888         snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
3889         snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
3890     {
3891         return A_EINVAL;
3892     }
3893     wmi_cache_configure_snrthreshold(wmip, snrCmd);
3894     return (wmi_send_snr_threshold_params(wmip, snrCmd));
3895 }
3896
3897 int
3898 wmi_clr_rssi_snr(struct wmi_t *wmip)
3899 {
3900     void    *osbuf;
3901
3902     osbuf = A_NETBUF_ALLOC(sizeof(int));
3903     if (osbuf == NULL) {
3904         return A_NO_MEMORY;
3905     }
3906
3907     return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
3908                             NO_SYNC_WMIFLAG));
3909 }
3910
3911 int
3912 wmi_set_lq_threshold_params(struct wmi_t *wmip,
3913                              WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
3914 {
3915     void    *osbuf;
3916     s8 size;
3917     WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
3918     /* These values are in ascending order */
3919     if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
3920         lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
3921         lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
3922         lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
3923         lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
3924         lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
3925
3926         return A_EINVAL;
3927     }
3928
3929     size = sizeof (*cmd);
3930
3931     osbuf = A_NETBUF_ALLOC(size);
3932     if (osbuf == NULL) {
3933         return A_NO_MEMORY;
3934     }
3935
3936     A_NETBUF_PUT(osbuf, size);
3937
3938     cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3939     A_MEMZERO(cmd, size);
3940     memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
3941
3942     return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
3943                             NO_SYNC_WMIFLAG));
3944 }
3945
3946 int
3947 wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
3948 {
3949     void    *osbuf;
3950     s8 size;
3951     WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
3952
3953     size = sizeof (*cmd);
3954
3955     osbuf = A_NETBUF_ALLOC(size);
3956     if (osbuf == NULL) {
3957         return A_NO_MEMORY;
3958     }
3959
3960     A_NETBUF_PUT(osbuf, size);
3961
3962     cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
3963     A_MEMZERO(cmd, size);
3964
3965     cmd->bitmask = mask;
3966
3967     return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
3968                             NO_SYNC_WMIFLAG));
3969 }
3970
3971 int
3972 wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
3973 {
3974     void *osbuf;
3975     WMIX_HB_CHALLENGE_RESP_CMD *cmd;
3976
3977     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3978     if (osbuf == NULL) {
3979         return A_NO_MEMORY;
3980     }
3981
3982     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3983
3984     cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
3985     cmd->cookie = cookie;
3986     cmd->source = source;
3987
3988     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
3989                               NO_SYNC_WMIFLAG));
3990 }
3991
3992 int
3993 wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
3994                             u16 tsr, bool rep, u16 size,
3995                             u32 valid)
3996 {
3997     void *osbuf;
3998     WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
3999
4000     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4001     if (osbuf == NULL) {
4002         return A_NO_MEMORY;
4003     }
4004
4005     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4006
4007     cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
4008     cmd->config.cfgmmask = mmask;
4009     cmd->config.cfgtsr = tsr;
4010     cmd->config.cfgrep = rep;
4011     cmd->config.cfgsize = size;
4012     cmd->config.cfgvalid = valid;
4013
4014     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
4015                               NO_SYNC_WMIFLAG));
4016 }
4017
4018 int
4019 wmi_get_stats_cmd(struct wmi_t *wmip)
4020 {
4021     return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4022 }
4023
4024 int
4025 wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
4026 {
4027     void *osbuf;
4028     WMI_ADD_BAD_AP_CMD *cmd;
4029
4030     if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
4031         return A_EINVAL;
4032     }
4033
4034     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4035     if (osbuf == NULL) {
4036         return A_NO_MEMORY;
4037     }
4038
4039     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4040
4041     cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4042     cmd->badApIndex = apIndex;
4043     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4044
4045     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4046 }
4047
4048 int
4049 wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
4050 {
4051     void *osbuf;
4052     WMI_DELETE_BAD_AP_CMD *cmd;
4053
4054     if (apIndex > WMI_MAX_BAD_AP_INDEX) {
4055         return A_EINVAL;
4056     }
4057
4058     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4059     if (osbuf == NULL) {
4060         return A_NO_MEMORY;
4061     }
4062
4063     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4064
4065     cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4066     cmd->badApIndex = apIndex;
4067
4068     return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
4069                          NO_SYNC_WMIFLAG));
4070 }
4071
4072 int
4073 wmi_abort_scan_cmd(struct wmi_t *wmip)
4074 {
4075     return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4076 }
4077
4078 int
4079 wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
4080 {
4081     void *osbuf;
4082     WMI_SET_TX_PWR_CMD *cmd;
4083
4084     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4085     if (osbuf == NULL) {
4086         return A_NO_MEMORY;
4087     }
4088
4089     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4090
4091     cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
4092     cmd->dbM = dbM;
4093
4094     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
4095 }
4096
4097 int
4098 wmi_get_txPwr_cmd(struct wmi_t *wmip)
4099 {
4100     return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4101 }
4102
4103 u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
4104 {
4105     u16 activeTsids=0;
4106
4107     LOCK_WMI(wmip);
4108     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4109     UNLOCK_WMI(wmip);
4110
4111     return activeTsids;
4112 }
4113
4114 int
4115 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4116 {
4117     return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4118 }
4119
4120 int
4121 wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
4122 {
4123     void *osbuf;
4124     u32 size = sizeof(u8);
4125     WMI_TARGET_ROAM_DATA *cmd;
4126
4127     osbuf = A_NETBUF_ALLOC(size);      /* no payload */
4128     if (osbuf == NULL) {
4129         return A_NO_MEMORY;
4130     }
4131
4132     A_NETBUF_PUT(osbuf, size);
4133
4134     cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
4135     cmd->roamDataType = roamDataType;
4136
4137     return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
4138                          NO_SYNC_WMIFLAG));
4139 }
4140
4141 int
4142 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
4143                       u8 size)
4144 {
4145     void *osbuf;
4146     WMI_SET_ROAM_CTRL_CMD *cmd;
4147
4148     osbuf = A_NETBUF_ALLOC(size);
4149     if (osbuf == NULL) {
4150         return A_NO_MEMORY;
4151     }
4152
4153     A_NETBUF_PUT(osbuf, size);
4154
4155     cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
4156     A_MEMZERO(cmd, size);
4157
4158     memcpy(cmd, p, size);
4159
4160     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4161                          NO_SYNC_WMIFLAG));
4162 }
4163
4164 int
4165 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4166                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
4167                             u8 size)
4168 {
4169     void *osbuf;
4170     WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
4171
4172     /* These timers can't be zero */
4173     if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
4174        !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
4175          pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
4176        !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
4177          pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
4178         return A_EINVAL;
4179
4180     osbuf = A_NETBUF_ALLOC(size);
4181     if (osbuf == NULL) {
4182         return A_NO_MEMORY;
4183     }
4184
4185     A_NETBUF_PUT(osbuf, size);
4186
4187     cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
4188     A_MEMZERO(cmd, size);
4189
4190     memcpy(cmd, pCmd, size);
4191
4192     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
4193                          NO_SYNC_WMIFLAG));
4194 }
4195
4196 int
4197 wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac,  u16 txop, u8 eCWmin,
4198                           u8 eCWmax, u8 aifsn)
4199 {
4200     void *osbuf;
4201     WMI_SET_ACCESS_PARAMS_CMD *cmd;
4202
4203     if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
4204         (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
4205     {
4206         return A_EINVAL;
4207     }
4208
4209     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4210     if (osbuf == NULL) {
4211         return A_NO_MEMORY;
4212     }
4213
4214     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4215
4216     cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4217     cmd->txop   = txop;
4218     cmd->eCWmin = eCWmin;
4219     cmd->eCWmax = eCWmax;
4220     cmd->aifsn  = aifsn;
4221     cmd->ac = ac;
4222
4223     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
4224                          NO_SYNC_WMIFLAG));
4225 }
4226
4227 int
4228 wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4229                          u8 trafficClass, u8 maxRetries,
4230                          u8 enableNotify)
4231 {
4232     void *osbuf;
4233     WMI_SET_RETRY_LIMITS_CMD *cmd;
4234
4235     if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
4236         (frameType != DATA_FRAMETYPE))
4237     {
4238         return A_EINVAL;
4239     }
4240
4241     if (maxRetries > WMI_MAX_RETRIES) {
4242         return A_EINVAL;
4243     }
4244
4245     if (frameType != DATA_FRAMETYPE) {
4246         trafficClass = 0;
4247     }
4248
4249     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4250     if (osbuf == NULL) {
4251         return A_NO_MEMORY;
4252     }
4253
4254     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4255
4256     cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
4257     cmd->frameType    = frameType;
4258     cmd->trafficClass = trafficClass;
4259     cmd->maxRetries   = maxRetries;
4260     cmd->enableNotify = enableNotify;
4261
4262     return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
4263                          NO_SYNC_WMIFLAG));
4264 }
4265
4266 void
4267 wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
4268 {
4269     if (bssid != NULL) {
4270         memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
4271     }
4272 }
4273
4274 int
4275 wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
4276 {
4277     void *osbuf;
4278     WMI_SET_OPT_MODE_CMD *cmd;
4279
4280     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4281     if (osbuf == NULL) {
4282         return A_NO_MEMORY;
4283     }
4284
4285     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4286
4287     cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4288     A_MEMZERO(cmd, sizeof(*cmd));
4289     cmd->optMode = optMode;
4290
4291     return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
4292                          SYNC_BOTH_WMIFLAG));
4293 }
4294
4295 int
4296 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
4297                       u8 frmType,
4298                       u8 *dstMacAddr,
4299                       u8 *bssid,
4300                       u16 optIEDataLen,
4301                       u8 *optIEData)
4302 {
4303     void *osbuf;
4304     WMI_OPT_TX_FRAME_CMD *cmd;
4305     osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
4306     if (osbuf == NULL) {
4307         return A_NO_MEMORY;
4308     }
4309
4310     A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
4311
4312     cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
4313     A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
4314
4315     cmd->frmType    = frmType;
4316     cmd->optIEDataLen   = optIEDataLen;
4317     //cmd->optIEData     = (u8 *)((int)cmd + sizeof(*cmd));
4318     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4319     memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4320     memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
4321
4322     return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4323                          NO_SYNC_WMIFLAG));
4324 }
4325
4326 int
4327 wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
4328 {
4329     void *osbuf;
4330     WMI_BEACON_INT_CMD *cmd;
4331
4332     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4333     if (osbuf == NULL) {
4334         return A_NO_MEMORY;
4335     }
4336
4337     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4338
4339     cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
4340     A_MEMZERO(cmd, sizeof(*cmd));
4341     cmd->beaconInterval = intvl;
4342
4343     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
4344             NO_SYNC_WMIFLAG));
4345 }
4346
4347
4348 int
4349 wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
4350 {
4351     void *osbuf;
4352     WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
4353
4354     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4355     if (osbuf == NULL) {
4356         return A_NO_MEMORY;
4357     }
4358
4359     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4360
4361     cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
4362     A_MEMZERO(cmd, sizeof(*cmd));
4363     cmd->voicePktSize = voicePktSize;
4364
4365     return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
4366             NO_SYNC_WMIFLAG));
4367 }
4368
4369
4370 int
4371 wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
4372 {
4373     void *osbuf;
4374     WMI_SET_MAX_SP_LEN_CMD *cmd;
4375
4376     /* maxSPLen is a two-bit value. If user trys to set anything
4377      * other than this, then its invalid
4378      */
4379     if(maxSPLen & ~0x03)
4380         return  A_EINVAL;
4381
4382     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4383     if (osbuf == NULL) {
4384         return A_NO_MEMORY;
4385     }
4386
4387     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4388
4389     cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
4390     A_MEMZERO(cmd, sizeof(*cmd));
4391     cmd->maxSPLen = maxSPLen;
4392
4393     return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
4394             NO_SYNC_WMIFLAG));
4395 }
4396
4397 u8 wmi_determine_userPriority(
4398     u8 *pkt,
4399     u32 layer2Pri)
4400 {
4401     u8 ipPri;
4402     iphdr *ipHdr = (iphdr *)pkt;
4403
4404     /* Determine IPTOS priority */
4405     /*
4406      * IP Tos format :
4407      *      (Refer Pg 57 WMM-test-plan-v1.2)
4408      * IP-TOS - 8bits
4409      *          : DSCP(6-bits) ECN(2-bits)
4410      *          : DSCP - P2 P1 P0 X X X
4411      *              where (P2 P1 P0) form 802.1D
4412      */
4413     ipPri = ipHdr->ip_tos >> 5;
4414     ipPri &= 0x7;
4415
4416     if ((layer2Pri & 0x7) > ipPri)
4417         return ((u8)layer2Pri & 0x7);
4418     else
4419         return ipPri;
4420 }
4421
4422 u8 convert_userPriority_to_trafficClass(u8 userPriority)
4423 {
4424     return  (up_to_ac[userPriority & 0x7]);
4425 }
4426
4427 u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
4428 {
4429     return wmip->wmi_powerMode;
4430 }
4431
4432 int
4433 wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
4434 {
4435     int ret = 0;
4436
4437 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
4438 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF  0
4439 #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF      0
4440 #define TSPEC_DELAY_BOUND_ATHEROS_DEF         0
4441 #define TSPEC_MEDIUM_TIME_ATHEROS_DEF         0
4442 #define TSPEC_SBA_ATHEROS_DEF                 0x2000  /* factor is 1 */
4443
4444     /* Verify TSPEC params for ATHEROS compliance */
4445     if(tspecCompliance == ATHEROS_COMPLIANCE) {
4446         if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
4447             (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
4448             (pCmd->minDataRate != pCmd->meanDataRate) ||
4449             (pCmd->minDataRate != pCmd->peakDataRate) ||
4450             (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
4451             (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
4452             (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
4453             (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
4454
4455             A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
4456             //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
4457             ret = A_EINVAL;
4458         }
4459     }
4460
4461     return ret;
4462 }
4463
4464 #ifdef CONFIG_HOST_TCMD_SUPPORT
4465 static int
4466 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
4467 {
4468
4469    A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4470
4471    return 0;
4472 }
4473
4474 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
4475
4476 int
4477 wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
4478 {
4479     void *osbuf;
4480     WMI_SET_AUTH_MODE_CMD *cmd;
4481
4482     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4483     if (osbuf == NULL) {
4484         return A_NO_MEMORY;
4485     }
4486
4487     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4488
4489     cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4490     A_MEMZERO(cmd, sizeof(*cmd));
4491     cmd->mode = mode;
4492
4493     return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
4494             NO_SYNC_WMIFLAG));
4495 }
4496
4497 int
4498 wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
4499 {
4500     void *osbuf;
4501     WMI_SET_REASSOC_MODE_CMD *cmd;
4502
4503     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4504     if (osbuf == NULL) {
4505         return A_NO_MEMORY;
4506     }
4507
4508     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4509
4510     cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4511     A_MEMZERO(cmd, sizeof(*cmd));
4512     cmd->mode = mode;
4513
4514     return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
4515             NO_SYNC_WMIFLAG));
4516 }
4517
4518 int
4519 wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
4520 {
4521     void *osbuf;
4522     WMI_SET_LPREAMBLE_CMD *cmd;
4523
4524     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4525     if (osbuf == NULL) {
4526         return A_NO_MEMORY;
4527     }
4528
4529     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4530
4531     cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
4532     A_MEMZERO(cmd, sizeof(*cmd));
4533     cmd->status = status;
4534     cmd->preamblePolicy = preamblePolicy;
4535
4536     return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
4537             NO_SYNC_WMIFLAG));
4538 }
4539
4540 int
4541 wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
4542 {
4543     void *osbuf;
4544     WMI_SET_RTS_CMD *cmd;
4545
4546     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4547     if (osbuf == NULL) {
4548         return A_NO_MEMORY;
4549     }
4550
4551     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4552
4553     cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
4554     A_MEMZERO(cmd, sizeof(*cmd));
4555     cmd->threshold = threshold;
4556
4557     return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
4558             NO_SYNC_WMIFLAG));
4559 }
4560
4561 int
4562 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
4563 {
4564     void *osbuf;
4565     WMI_SET_WMM_CMD *cmd;
4566
4567     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4568     if (osbuf == NULL) {
4569         return A_NO_MEMORY;
4570     }
4571
4572     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4573
4574     cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
4575     A_MEMZERO(cmd, sizeof(*cmd));
4576     cmd->status = status;
4577
4578     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
4579             NO_SYNC_WMIFLAG));
4580
4581 }
4582
4583 int
4584 wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
4585 {
4586     void *osbuf;
4587     WMI_SET_QOS_SUPP_CMD *cmd;
4588
4589     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4590     if (osbuf == NULL) {
4591         return A_NO_MEMORY;
4592     }
4593
4594     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4595
4596     cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
4597     A_MEMZERO(cmd, sizeof(*cmd));
4598     cmd->status = status;
4599     return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
4600             NO_SYNC_WMIFLAG));
4601 }
4602
4603
4604 int
4605 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
4606 {
4607     void *osbuf;
4608     WMI_SET_WMM_TXOP_CMD *cmd;
4609
4610     if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
4611         return A_EINVAL;
4612
4613     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4614     if (osbuf == NULL) {
4615         return A_NO_MEMORY;
4616     }
4617
4618     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4619
4620     cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
4621     A_MEMZERO(cmd, sizeof(*cmd));
4622     cmd->txopEnable = cfg;
4623
4624     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
4625             NO_SYNC_WMIFLAG));
4626
4627 }
4628
4629 int
4630 wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
4631 {
4632     void *osbuf;
4633     WMI_AP_SET_COUNTRY_CMD *cmd;
4634
4635     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4636     if (osbuf == NULL) {
4637         return A_NO_MEMORY;
4638     }
4639
4640     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4641
4642     cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
4643     A_MEMZERO(cmd, sizeof(*cmd));
4644     memcpy(cmd->countryCode,countryCode,3);
4645
4646     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
4647             NO_SYNC_WMIFLAG));
4648 }
4649
4650 #ifdef CONFIG_HOST_TCMD_SUPPORT
4651 /* WMI  layer doesn't need to know the data type of the test cmd.
4652    This would be beneficial for customers like Qualcomm, who might
4653    have different test command requirements from different manufacturers
4654  */
4655 int
4656 wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
4657 {
4658     void *osbuf;
4659     char *data;
4660
4661     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4662
4663     osbuf= A_NETBUF_ALLOC(len);
4664     if(osbuf == NULL)
4665     {
4666         return A_NO_MEMORY;
4667     }
4668     A_NETBUF_PUT(osbuf, len);
4669     data = A_NETBUF_DATA(osbuf);
4670     memcpy(data, buf, len);
4671
4672     return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4673          NO_SYNC_WMIFLAG));
4674 }
4675
4676 #endif
4677
4678 int
4679 wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
4680 {
4681     void *osbuf;
4682     WMI_SET_BT_STATUS_CMD *cmd;
4683
4684     AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
4685
4686     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4687     if (osbuf == NULL) {
4688         return A_NO_MEMORY;
4689     }
4690
4691     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4692
4693     cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4694     A_MEMZERO(cmd, sizeof(*cmd));
4695     cmd->streamType = streamType;
4696     cmd->status = status;
4697
4698     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
4699             NO_SYNC_WMIFLAG));
4700 }
4701
4702 int
4703 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
4704 {
4705     void *osbuf;
4706     WMI_SET_BT_PARAMS_CMD* alloc_cmd;
4707
4708     AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
4709
4710     if (cmd->paramType == BT_PARAM_SCO) {
4711       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger,
4712         cmd->info.scoParams.dataResponseTimeout,
4713         cmd->info.scoParams.stompScoRules,
4714         cmd->info.scoParams.scoOptFlags,
4715         cmd->info.scoParams.stompDutyCyleVal,
4716         cmd->info.scoParams.stompDutyCyleMaxVal,
4717         cmd->info.scoParams.psPollLatencyFraction,
4718         cmd->info.scoParams.noSCOSlots,
4719         cmd->info.scoParams.noIdleSlots,
4720         cmd->info.scoParams.scoOptOffRssi,
4721         cmd->info.scoParams.scoOptOnRssi,
4722         cmd->info.scoParams.scoOptRtsCount));
4723     }
4724     else if (cmd->paramType == BT_PARAM_A2DP) {
4725       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
4726         cmd->info.a2dpParams.a2dpBurstCntMin,
4727         cmd->info.a2dpParams.a2dpDataRespTimeout,
4728         cmd->info.a2dpParams.a2dpOptFlags,
4729         cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
4730         cmd->info.a2dpParams.a2dpOptOffRssi,
4731         cmd->info.a2dpParams.a2dpOptOnRssi,
4732         cmd->info.a2dpParams.a2dpOptRtsCount));
4733     }
4734     else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
4735       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
4736     }
4737     else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
4738       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
4739     }
4740     else if (cmd->paramType == BT_PARAM_ACLCOEX) {
4741       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
4742         cmd->info.aclCoexParams.aclBtMediumUsageTime,
4743         cmd->info.aclCoexParams.aclDataRespTimeout));
4744     }
4745     else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
4746       A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
4747     }
4748
4749     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4750     if (osbuf == NULL) {
4751         return A_NO_MEMORY;
4752     }
4753
4754     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4755
4756     alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4757     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4758     memcpy(alloc_cmd, cmd, sizeof(*cmd));
4759
4760     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4761             NO_SYNC_WMIFLAG));
4762 }
4763
4764 int
4765 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
4766 {
4767         void *osbuf;
4768     WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
4769
4770     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4771     if (osbuf == NULL) {
4772         return A_NO_MEMORY;
4773     }
4774     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4775     alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
4776     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4777         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
4778     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4779                          NO_SYNC_WMIFLAG));
4780
4781 }
4782
4783
4784 int
4785 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
4786                                                 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
4787 {
4788         void *osbuf;
4789     WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
4790
4791     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4792     if (osbuf == NULL) {
4793         return A_NO_MEMORY;
4794     }
4795     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4796     alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
4797     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4798     memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
4799     A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
4800     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
4801                          NO_SYNC_WMIFLAG));
4802
4803 }
4804
4805 int
4806 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
4807                                                 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
4808 {
4809         void *osbuf;
4810     WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
4811
4812     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4813     if (osbuf == NULL) {
4814         return A_NO_MEMORY;
4815     }
4816     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4817     alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4818     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4819         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
4820     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
4821                          NO_SYNC_WMIFLAG));
4822
4823 }
4824
4825 int
4826 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
4827                                                 WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
4828 {
4829         void *osbuf;
4830     WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
4831
4832     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4833     if (osbuf == NULL) {
4834         return A_NO_MEMORY;
4835     }
4836     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4837     alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4838     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4839         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
4840     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
4841                          NO_SYNC_WMIFLAG));
4842
4843 }
4844
4845 int
4846 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
4847                                                 WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
4848 {
4849         void *osbuf;
4850     WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
4851
4852     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4853     if (osbuf == NULL) {
4854         return A_NO_MEMORY;
4855     }
4856     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4857     alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4858     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4859         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
4860     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
4861                          NO_SYNC_WMIFLAG));
4862
4863 }
4864
4865 int
4866 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
4867                                                 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
4868 {
4869         void *osbuf;
4870     WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
4871
4872     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4873     if (osbuf == NULL) {
4874         return A_NO_MEMORY;
4875     }
4876     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4877     alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4878     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4879         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
4880     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
4881                          NO_SYNC_WMIFLAG));
4882
4883 }
4884
4885 int
4886 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
4887 {
4888         void *osbuf;
4889         WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
4890
4891         osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4892         if (osbuf == NULL) {
4893                         return A_NO_MEMORY;
4894         }
4895         A_NETBUF_PUT(osbuf, sizeof(*cmd));
4896         alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
4897         A_MEMZERO(alloc_cmd, sizeof(*cmd));
4898         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
4899         return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
4900                                                          NO_SYNC_WMIFLAG));
4901
4902 }
4903
4904 int
4905 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
4906                                         WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
4907 {
4908         void *osbuf;
4909         WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
4910
4911         osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4912         if (osbuf == NULL) {
4913                         return A_NO_MEMORY;
4914         }
4915         A_NETBUF_PUT(osbuf, sizeof(*cmd));
4916         alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4917         A_MEMZERO(alloc_cmd, sizeof(*cmd));
4918         memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
4919         return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
4920                                                                  NO_SYNC_WMIFLAG));
4921
4922 }
4923
4924 int
4925 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
4926 {
4927         void *osbuf;
4928         WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
4929
4930         osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4931         if (osbuf == NULL) {
4932                         return A_NO_MEMORY;
4933         }
4934         A_NETBUF_PUT(osbuf, sizeof(*cmd));
4935         alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4936         A_MEMZERO(alloc_cmd, sizeof(*cmd));
4937         memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
4938         return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
4939                                                          NO_SYNC_WMIFLAG));
4940
4941 }
4942
4943 int
4944 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
4945 {
4946
4947     return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
4948
4949 }
4950
4951 int
4952 wmi_get_keepalive_configured(struct wmi_t *wmip)
4953 {
4954     void *osbuf;
4955     WMI_GET_KEEPALIVE_CMD *cmd;
4956     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4957     if (osbuf == NULL) {
4958         return A_NO_MEMORY;
4959     }
4960     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4961     cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4962     A_MEMZERO(cmd, sizeof(*cmd));
4963     return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
4964                          NO_SYNC_WMIFLAG));
4965 }
4966
4967 u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
4968 {
4969     return wmip->wmi_keepaliveInterval;
4970 }
4971
4972 int
4973 wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
4974 {
4975     void *osbuf;
4976     WMI_SET_KEEPALIVE_CMD *cmd;
4977
4978     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4979     if (osbuf == NULL) {
4980         return A_NO_MEMORY;
4981     }
4982
4983     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4984
4985     cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4986     A_MEMZERO(cmd, sizeof(*cmd));
4987     cmd->keepaliveInterval = keepaliveInterval;
4988     wmip->wmi_keepaliveInterval = keepaliveInterval;
4989
4990     return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
4991                          NO_SYNC_WMIFLAG));
4992 }
4993
4994 int
4995 wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
4996 {
4997     void *osbuf;
4998     WMI_SET_PARAMS_CMD *cmd;
4999
5000     osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
5001     if (osbuf == NULL) {
5002         return A_NO_MEMORY;
5003     }
5004
5005     A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
5006
5007     cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5008     A_MEMZERO(cmd, sizeof(*cmd));
5009     cmd->opcode = opcode;
5010     cmd->length = length;
5011     memcpy(cmd->buffer, buffer, length);
5012
5013     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5014                          NO_SYNC_WMIFLAG));
5015 }
5016
5017
5018 int
5019 wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5020 {
5021     void *osbuf;
5022     WMI_SET_MCAST_FILTER_CMD *cmd;
5023
5024     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5025     if (osbuf == NULL) {
5026         return A_NO_MEMORY;
5027     }
5028
5029     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5030
5031     cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5032     cmd->multicast_mac[0] = 0x01;
5033     cmd->multicast_mac[1] = 0x00;
5034     cmd->multicast_mac[2] = 0x5e;
5035     cmd->multicast_mac[3] = dot2&0x7F;
5036     cmd->multicast_mac[4] = dot3;
5037     cmd->multicast_mac[5] = dot4;
5038
5039     return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
5040                          NO_SYNC_WMIFLAG));
5041 }
5042
5043
5044 int
5045 wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5046 {
5047     void *osbuf;
5048     WMI_SET_MCAST_FILTER_CMD *cmd;
5049
5050     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5051     if (osbuf == NULL) {
5052         return A_NO_MEMORY;
5053     }
5054
5055     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5056
5057     cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5058     cmd->multicast_mac[0] = 0x01;
5059     cmd->multicast_mac[1] = 0x00;
5060     cmd->multicast_mac[2] = 0x5e;
5061     cmd->multicast_mac[3] = dot2&0x7F;
5062     cmd->multicast_mac[4] = dot3;
5063     cmd->multicast_mac[5] = dot4;
5064
5065     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID,
5066                          NO_SYNC_WMIFLAG));
5067 }
5068
5069 int
5070 wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
5071 {
5072     void *osbuf;
5073     WMI_MCAST_FILTER_CMD *cmd;
5074
5075     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5076     if (osbuf == NULL) {
5077         return A_NO_MEMORY;
5078     }
5079
5080     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5081
5082     cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5083     cmd->enable = enable;
5084
5085     return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
5086                          NO_SYNC_WMIFLAG));
5087 }
5088
5089 int
5090 wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5091                   u8 *ieInfo)
5092 {
5093     void *osbuf;
5094     WMI_SET_APPIE_CMD *cmd;
5095     u16 cmdLen;
5096
5097     cmdLen = sizeof(*cmd) + ieLen - 1;
5098     osbuf = A_NETBUF_ALLOC(cmdLen);
5099     if (osbuf == NULL) {
5100         return A_NO_MEMORY;
5101     }
5102
5103     A_NETBUF_PUT(osbuf, cmdLen);
5104
5105     cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
5106     A_MEMZERO(cmd, cmdLen);
5107
5108     cmd->mgmtFrmType = mgmtFrmType;
5109     cmd->ieLen = ieLen;
5110     memcpy(cmd->ieInfo, ieInfo, ieLen);
5111
5112     return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5113 }
5114
5115 int
5116 wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
5117 {
5118     void *osbuf;
5119     u8 *data;
5120
5121     osbuf = A_NETBUF_ALLOC(dataLen);
5122     if (osbuf == NULL) {
5123         return A_NO_MEMORY;
5124     }
5125
5126     A_NETBUF_PUT(osbuf, dataLen);
5127
5128     data = A_NETBUF_DATA(osbuf);
5129
5130     memcpy(data, cmd, dataLen);
5131
5132     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5133 }
5134
5135 s32 wmi_get_rate(s8 rateindex)
5136 {
5137     if (rateindex == RATE_AUTO) {
5138         return 0;
5139     } else {
5140         return(wmi_rateTable[(u32) rateindex][0]);
5141     }
5142 }
5143
5144 void
5145 wmi_node_return (struct wmi_t *wmip, bss_t *bss)
5146 {
5147     if (NULL != bss)
5148     {
5149         wlan_node_return (&wmip->wmi_scan_table, bss);
5150     }
5151 }
5152
5153 void
5154 wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
5155 {
5156     wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5157 }
5158
5159 bss_t *
5160 wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
5161                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
5162 {
5163     bss_t *node = NULL;
5164     node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
5165                                ssidLength, bIsWPA2, bMatchSSID);
5166     return node;
5167 }
5168
5169
5170 #ifdef THREAD_X
5171 void
5172 wmi_refresh_scan_table (struct wmi_t *wmip)
5173 {
5174         wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5175 }
5176 #endif
5177
5178 void
5179 wmi_free_allnodes(struct wmi_t *wmip)
5180 {
5181     wlan_free_allnodes(&wmip->wmi_scan_table);
5182 }
5183
5184 bss_t *
5185 wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
5186 {
5187     bss_t *ni=NULL;
5188     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5189     return ni;
5190 }
5191
5192 void
5193 wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
5194 {
5195     bss_t *ni=NULL;
5196
5197     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5198     if (ni != NULL) {
5199         wlan_node_reclaim(&wmip->wmi_scan_table, ni);
5200     }
5201
5202     return;
5203 }
5204
5205 int
5206 wmi_dset_open_reply(struct wmi_t *wmip,
5207                     u32 status,
5208                     u32 access_cookie,
5209                     u32 dset_size,
5210                     u32 dset_version,
5211                     u32 targ_handle,
5212                     u32 targ_reply_fn,
5213                     u32 targ_reply_arg)
5214 {
5215     void *osbuf;
5216     WMIX_DSETOPEN_REPLY_CMD *open_reply;
5217
5218     A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
5219
5220     osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
5221     if (osbuf == NULL) {
5222         return A_NO_MEMORY;
5223     }
5224
5225     A_NETBUF_PUT(osbuf, sizeof(*open_reply));
5226     open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5227
5228     open_reply->status                   = status;
5229     open_reply->targ_dset_handle         = targ_handle;
5230     open_reply->targ_reply_fn            = targ_reply_fn;
5231     open_reply->targ_reply_arg           = targ_reply_arg;
5232     open_reply->access_cookie            = access_cookie;
5233     open_reply->size                     = dset_size;
5234     open_reply->version                  = dset_version;
5235
5236     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
5237                              NO_SYNC_WMIFLAG));
5238 }
5239
5240 static int
5241 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5242 {
5243     WMI_PMKID_LIST_REPLY *reply;
5244     u32 expected_len;
5245
5246     if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
5247         return A_EINVAL;
5248     }
5249     reply = (WMI_PMKID_LIST_REPLY *)datap;
5250     expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
5251
5252     if (len < expected_len) {
5253         return A_EINVAL;
5254     }
5255
5256     A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
5257                            reply->pmkidList, reply->bssidList[0]);
5258
5259     return 0;
5260 }
5261
5262
5263 static int
5264 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5265 {
5266     WMI_SET_PARAMS_REPLY *reply;
5267
5268     if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
5269         return A_EINVAL;
5270     }
5271     reply = (WMI_SET_PARAMS_REPLY *)datap;
5272
5273     if (0 == reply->status)
5274     {
5275
5276     }
5277     else
5278     {
5279
5280     }
5281
5282     return 0;
5283 }
5284
5285
5286 #ifdef CONFIG_HOST_DSET_SUPPORT
5287 int
5288 wmi_dset_data_reply(struct wmi_t *wmip,
5289                     u32 status,
5290                     u8 *user_buf,
5291                     u32 length,
5292                     u32 targ_buf,
5293                     u32 targ_reply_fn,
5294                     u32 targ_reply_arg)
5295 {
5296     void *osbuf;
5297     WMIX_DSETDATA_REPLY_CMD *data_reply;
5298     u32 size;
5299
5300     size = sizeof(*data_reply) + length;
5301
5302     if (size <= length) {
5303         return A_ERROR;
5304     }
5305
5306     A_DPRINTF(DBG_WMI,
5307         (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
5308
5309     osbuf = A_NETBUF_ALLOC(size);
5310     if (osbuf == NULL) {
5311         return A_NO_MEMORY;
5312     }
5313     A_NETBUF_PUT(osbuf, size);
5314     data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5315
5316     data_reply->status                     = status;
5317     data_reply->targ_buf                   = targ_buf;
5318     data_reply->targ_reply_fn              = targ_reply_fn;
5319     data_reply->targ_reply_arg             = targ_reply_arg;
5320     data_reply->length                     = length;
5321
5322     if (status == 0) {
5323         if (a_copy_from_user(data_reply->buf, user_buf, length)) {
5324             A_NETBUF_FREE(osbuf);
5325             return A_ERROR;
5326         }
5327     }
5328
5329     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
5330                              NO_SYNC_WMIFLAG));
5331 }
5332 #endif /* CONFIG_HOST_DSET_SUPPORT */
5333
5334 int
5335 wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
5336 {
5337     void *osbuf;
5338     char *cmd;
5339
5340     wps_enable = status;
5341
5342     osbuf = a_netbuf_alloc(sizeof(1));
5343     if (osbuf == NULL) {
5344         return A_NO_MEMORY;
5345     }
5346
5347     a_netbuf_put(osbuf, sizeof(1));
5348
5349     cmd = (char *)(a_netbuf_to_data(osbuf));
5350
5351     A_MEMZERO(cmd, sizeof(*cmd));
5352     cmd[0] = (status?1:0);
5353     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
5354                          NO_SYNC_WMIFLAG));
5355 }
5356
5357 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
5358 int
5359 wmi_prof_cfg_cmd(struct wmi_t *wmip,
5360                  u32 period,
5361                  u32 nbins)
5362 {
5363     void *osbuf;
5364     WMIX_PROF_CFG_CMD *cmd;
5365
5366     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5367     if (osbuf == NULL) {
5368         return A_NO_MEMORY;
5369     }
5370
5371     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5372
5373     cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
5374     A_MEMZERO(cmd, sizeof(*cmd));
5375     cmd->period = period;
5376     cmd->nbins  = nbins;
5377
5378     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
5379 }
5380
5381 int
5382 wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
5383 {
5384     void *osbuf;
5385     WMIX_PROF_ADDR_SET_CMD *cmd;
5386
5387     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5388     if (osbuf == NULL) {
5389         return A_NO_MEMORY;
5390     }
5391
5392     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5393
5394     cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
5395     A_MEMZERO(cmd, sizeof(*cmd));
5396     cmd->addr = addr;
5397
5398     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
5399 }
5400
5401 int
5402 wmi_prof_start_cmd(struct wmi_t *wmip)
5403 {
5404     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5405 }
5406
5407 int
5408 wmi_prof_stop_cmd(struct wmi_t *wmip)
5409 {
5410     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5411 }
5412
5413 int
5414 wmi_prof_count_get_cmd(struct wmi_t *wmip)
5415 {
5416     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
5417 }
5418
5419 /* Called to handle WMIX_PROF_CONT_EVENTID */
5420 static int
5421 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
5422 {
5423     WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
5424
5425     A_DPRINTF(DBG_WMI,
5426         (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
5427         prof_data->addr, prof_data->count));
5428
5429     A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
5430
5431     return 0;
5432 }
5433 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5434
5435 #ifdef OS_ROAM_MANAGEMENT
5436
5437 #define ETHERNET_MAC_ADDRESS_LENGTH    6
5438
5439 void
5440 wmi_scan_indication (struct wmi_t *wmip)
5441 {
5442     struct ieee80211_node_table *nt;
5443     u32 gen;
5444     u32 size;
5445     u32 bsssize;
5446     bss_t *bss;
5447     u32 numbss;
5448     PNDIS_802_11_BSSID_SCAN_INFO psi;
5449     PBYTE  pie;
5450     NDIS_802_11_FIXED_IEs *pFixed;
5451     NDIS_802_11_VARIABLE_IEs *pVar;
5452     u32 RateSize;
5453
5454     struct ar6kScanIndication
5455     {
5456         NDIS_802_11_STATUS_INDICATION     ind;
5457         NDIS_802_11_BSSID_SCAN_INFO_LIST  slist;
5458     } *pAr6kScanIndEvent;
5459
5460     nt = &wmip->wmi_scan_table;
5461
5462     ++nt->nt_si_gen;
5463
5464
5465     gen = nt->nt_si_gen;
5466
5467     size = offsetof(struct ar6kScanIndication, slist) +
5468            offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
5469
5470     numbss = 0;
5471
5472     IEEE80211_NODE_LOCK(nt);
5473
5474     //calc size
5475     for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5476         if (bss->ni_si_gen != gen) {
5477             bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
5478             bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5479
5480 #ifdef SUPPORT_WPA2
5481             if (bss->ni_cie.ie_rsn) {
5482                 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5483             }
5484 #endif
5485             if (bss->ni_cie.ie_wpa) {
5486                 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5487             }
5488
5489             // bsssize must be a multiple of 4 to maintain alignment.
5490             bsssize = (bsssize + 3) & ~3;
5491
5492             size += bsssize;
5493
5494             numbss++;
5495         }
5496     }
5497
5498     if (0 == numbss)
5499     {
5500 //        RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
5501         ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
5502         IEEE80211_NODE_UNLOCK (nt);
5503         return;
5504     }
5505
5506     pAr6kScanIndEvent = A_MALLOC(size);
5507
5508     if (NULL == pAr6kScanIndEvent)
5509     {
5510         IEEE80211_NODE_UNLOCK(nt);
5511         return;
5512     }
5513
5514     A_MEMZERO(pAr6kScanIndEvent, size);
5515
5516     //copy data
5517     pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
5518     pAr6kScanIndEvent->slist.Version = 1;
5519     pAr6kScanIndEvent->slist.NumItems = numbss;
5520
5521     psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
5522
5523     for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5524         if (bss->ni_si_gen != gen) {
5525
5526             bss->ni_si_gen = gen;
5527
5528             //Set scan time
5529             psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
5530
5531             // Copy data to bssid_ex
5532             bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
5533             bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5534
5535 #ifdef SUPPORT_WPA2
5536             if (bss->ni_cie.ie_rsn) {
5537                 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5538             }
5539 #endif
5540             if (bss->ni_cie.ie_wpa) {
5541                 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5542             }
5543
5544             // bsssize must be a multiple of 4 to maintain alignment.
5545             bsssize = (bsssize + 3) & ~3;
5546
5547             psi->Bssid.Length = bsssize;
5548
5549             memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
5550
5551
5552 //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
5553 //  ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
5554 //            RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
5555
5556             psi->Bssid.Ssid.SsidLength = 0;
5557             pie = bss->ni_cie.ie_ssid;
5558
5559             if (pie) {
5560                 // Format of SSID IE is:
5561                 //  Type   (1 octet)
5562                 //  Length (1 octet)
5563                 //  SSID (Length octets)
5564                 //
5565                 //  Validation of the IE should have occurred within WMI.
5566                 //
5567                 if (pie[1] <= 32) {
5568                     psi->Bssid.Ssid.SsidLength = pie[1];
5569                     memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
5570                 }
5571             }
5572             psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
5573
5574             //Post the RSSI value relative to the Standard Noise floor value.
5575             psi->Bssid.Rssi = bss->ni_rssi;
5576
5577             if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
5578
5579                 if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
5580                     psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
5581                 }
5582                 else {
5583                     psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
5584                 }
5585             }
5586             else {
5587                 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
5588             }
5589
5590             psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
5591             psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
5592             psi->Bssid.Configuration.ATIMWindow =  0;
5593             psi->Bssid.Configuration.DSConfig =  bss->ni_cie.ie_chan * 1000;
5594             psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
5595
5596             RateSize = 0;
5597             pie = bss->ni_cie.ie_rates;
5598             if (pie) {
5599                 RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
5600                 memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
5601             }
5602             pie = bss->ni_cie.ie_xrates;
5603             if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
5604                 memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
5605                        (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
5606             }
5607
5608             // Copy the fixed IEs
5609             psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
5610
5611             pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
5612             memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
5613             pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
5614             pFixed->Capabilities = bss->ni_cie.ie_capInfo;
5615
5616             // Copy selected variable IEs
5617
5618             pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
5619
5620 #ifdef SUPPORT_WPA2
5621             // Copy the WPAv2 IE
5622             if (bss->ni_cie.ie_rsn) {
5623                 pie = bss->ni_cie.ie_rsn;
5624                 psi->Bssid.IELength += pie[1] + 2;
5625                 memcpy(pVar, pie, pie[1] + 2);
5626                 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5627             }
5628 #endif
5629             // Copy the WPAv1 IE
5630             if (bss->ni_cie.ie_wpa) {
5631                 pie = bss->ni_cie.ie_wpa;
5632                 psi->Bssid.IELength += pie[1] + 2;
5633                 memcpy(pVar, pie, pie[1] + 2);
5634                 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5635             }
5636
5637             // Advance buffer pointer
5638             psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
5639         }
5640     }
5641
5642     IEEE80211_NODE_UNLOCK(nt);
5643
5644 //    wmi_free_allnodes(wmip);
5645
5646 //    RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
5647
5648     ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
5649
5650     kfree(pAr6kScanIndEvent);
5651 }
5652 #endif
5653
5654 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5655                            u32 size)
5656 {
5657     u32 index;
5658     u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
5659
5660     /* The list is already in sorted order. Get the next lower value */
5661     for (index = 0; index < size; index ++) {
5662         if (rssi < sq_thresh->upper_threshold[index]) {
5663             threshold = (u8)sq_thresh->upper_threshold[index];
5664             break;
5665         }
5666     }
5667
5668     return threshold;
5669 }
5670
5671 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5672                            u32 size)
5673 {
5674     u32 index;
5675     u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
5676
5677     /* The list is already in sorted order. Get the next lower value */
5678     for (index = 0; index < size; index ++) {
5679         if (rssi > sq_thresh->lower_threshold[index]) {
5680             threshold = (u8)sq_thresh->lower_threshold[index];
5681             break;
5682         }
5683     }
5684
5685     return threshold;
5686 }
5687 static int
5688 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5689                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5690 {
5691     void    *osbuf;
5692     s8 size;
5693     WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
5694
5695     size = sizeof (*cmd);
5696
5697     osbuf = A_NETBUF_ALLOC(size);
5698     if (osbuf == NULL) {
5699         return A_NO_MEMORY;
5700     }
5701
5702     A_NETBUF_PUT(osbuf, size);
5703
5704     cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5705     A_MEMZERO(cmd, size);
5706     memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
5707
5708     return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5709                             NO_SYNC_WMIFLAG));
5710 }
5711 static int
5712 wmi_send_snr_threshold_params(struct wmi_t *wmip,
5713                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5714 {
5715     void    *osbuf;
5716     s8 size;
5717     WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
5718
5719     size = sizeof (*cmd);
5720
5721     osbuf = A_NETBUF_ALLOC(size);
5722     if (osbuf == NULL) {
5723         return A_NO_MEMORY;
5724     }
5725
5726     A_NETBUF_PUT(osbuf, size);
5727     cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5728     A_MEMZERO(cmd, size);
5729     memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
5730
5731     return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5732                             NO_SYNC_WMIFLAG));
5733 }
5734
5735 int
5736 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
5737 {
5738     void *osbuf;
5739     WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
5740
5741     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5742     if (osbuf == NULL) {
5743         return A_NO_MEMORY;
5744     }
5745
5746     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5747
5748     alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
5749     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5750     memcpy(alloc_cmd, cmd, sizeof(*cmd));
5751
5752     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5753             NO_SYNC_WMIFLAG));
5754 }
5755
5756 bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
5757 {
5758     wmi_get_current_bssid (wmip, id);
5759     return wlan_node_remove (&wmip->wmi_scan_table, id);
5760 }
5761
5762 int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
5763 {
5764     wlan_setup_node (&wmip->wmi_scan_table, bss, id);
5765     return 0;
5766 }
5767
5768 static int
5769 wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5770 {
5771     WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
5772
5773     A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
5774
5775     return 0;
5776 }
5777
5778
5779 static int
5780 wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5781 {
5782     WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
5783
5784     A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
5785
5786     return 0;
5787 }
5788
5789 static int
5790 wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5791 {
5792     WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
5793
5794     A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
5795
5796     return 0;
5797 }
5798
5799 int
5800 wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5801 {
5802         A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5803
5804     A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
5805
5806      return 0;
5807 }
5808
5809
5810 int
5811 wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
5812 {
5813         A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5814
5815     A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
5816
5817      return 0;
5818
5819 }
5820
5821 static int
5822 wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5823 {
5824     WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
5825     A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
5826
5827     return 0;
5828 }
5829
5830 ////////////////////////////////////////////////////////////////////////////////
5831 ////                                                                        ////
5832 ////                AP mode functions                                       ////
5833 ////                                                                        ////
5834 ////////////////////////////////////////////////////////////////////////////////
5835 /*
5836  * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
5837  *
5838  * When AR6K in AP mode, This command will be called after
5839  * changing ssid, channel etc. It will pass the profile to
5840  * target with a flag which will indicate which parameter changed,
5841  * also if this flag is 0, there was no change in parametes, so
5842  * commit cmd will not be sent to target. Without calling this IOCTL
5843  * the changes will not take effect.
5844  */
5845 int
5846 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
5847 {
5848     void *osbuf;
5849     WMI_CONNECT_CMD *cm;
5850
5851     osbuf = A_NETBUF_ALLOC(sizeof(*cm));
5852     if (osbuf == NULL) {
5853         return A_NO_MEMORY;
5854     }
5855
5856     A_NETBUF_PUT(osbuf, sizeof(*cm));
5857     cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
5858     A_MEMZERO(cm, sizeof(*cm));
5859
5860     memcpy(cm,p,sizeof(*cm));
5861
5862     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
5863 }
5864
5865 /*
5866  * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
5867  *
5868  * This command will be used to enable/disable hidden ssid functioanlity of
5869  * beacon. If it is enabled, ssid will be NULL in beacon.
5870  */
5871 int
5872 wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
5873 {
5874     void *osbuf;
5875     WMI_AP_HIDDEN_SSID_CMD *hs;
5876
5877     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
5878     if (osbuf == NULL) {
5879         return A_NO_MEMORY;
5880     }
5881
5882     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
5883     hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
5884     A_MEMZERO(hs, sizeof(*hs));
5885
5886     hs->hidden_ssid          = hidden_ssid;
5887
5888     A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
5889     return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
5890 }
5891
5892 /*
5893  * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
5894  *
5895  * This command is used to limit max num of STA that can connect
5896  * with this AP. This value should not exceed AP_MAX_NUM_STA (this
5897  * is max num of STA supported by AP). Value was already validated
5898  * in ioctl.c
5899  */
5900 int
5901 wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
5902 {
5903     void *osbuf;
5904     WMI_AP_SET_NUM_STA_CMD *ns;
5905
5906     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
5907     if (osbuf == NULL) {
5908         return A_NO_MEMORY;
5909     }
5910
5911     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
5912     ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
5913     A_MEMZERO(ns, sizeof(*ns));
5914
5915     ns->num_sta          = num_sta;
5916
5917     A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
5918     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
5919 }
5920
5921 /*
5922  * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
5923  *
5924  * This command is used to send list of mac of STAs which will
5925  * be allowed to connect with this AP. When this list is empty
5926  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5927  */
5928 int
5929 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
5930 {
5931     void *osbuf;
5932     WMI_AP_ACL_MAC_CMD *a;
5933
5934     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
5935     if (osbuf == NULL) {
5936         return A_NO_MEMORY;
5937     }
5938
5939     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
5940     a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
5941     A_MEMZERO(a, sizeof(*a));
5942     memcpy(a,acl,sizeof(*acl));
5943
5944     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
5945 }
5946
5947 /*
5948  * IOCTL: AR6000_XIOCTL_AP_SET_MLME
5949  *
5950  * This command is used to send list of mac of STAs which will
5951  * be allowed to connect with this AP. When this list is empty
5952  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5953  */
5954 int
5955 wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
5956 {
5957     void *osbuf;
5958     WMI_AP_SET_MLME_CMD *mlme;
5959
5960     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
5961     if (osbuf == NULL) {
5962         return A_NO_MEMORY;
5963     }
5964
5965     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
5966     mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
5967     A_MEMZERO(mlme, sizeof(*mlme));
5968
5969     mlme->cmd = cmd;
5970     memcpy(mlme->mac, mac, ATH_MAC_LEN);
5971     mlme->reason = reason;
5972
5973     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
5974 }
5975
5976 static int
5977 wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5978 {
5979     WMI_PSPOLL_EVENT *ev;
5980
5981     if (len < sizeof(WMI_PSPOLL_EVENT)) {
5982         return A_EINVAL;
5983     }
5984     ev = (WMI_PSPOLL_EVENT *)datap;
5985
5986     A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
5987     return 0;
5988 }
5989
5990 static int
5991 wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
5992 {
5993     A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
5994     return 0;
5995 }
5996
5997 #ifdef WAPI_ENABLE
5998 static int
5999 wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6000 {
6001     u8 *ev;
6002
6003     if (len < 7) {
6004         return A_EINVAL;
6005     }
6006     ev = (u8 *)datap;
6007
6008     A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
6009     return 0;
6010 }
6011 #endif
6012
6013 int
6014 wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
6015 {
6016     WMI_AP_SET_PVB_CMD *cmd;
6017     void *osbuf = NULL;
6018
6019     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
6020     if (osbuf == NULL) {
6021         return A_NO_MEMORY;
6022     }
6023
6024     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
6025     cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
6026     A_MEMZERO(cmd, sizeof(*cmd));
6027
6028     cmd->aid = aid;
6029     cmd->flag = flag;
6030
6031     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
6032 }
6033
6034 int
6035 wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
6036 {
6037     WMI_AP_CONN_INACT_CMD *cmd;
6038     void *osbuf = NULL;
6039
6040     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
6041     if (osbuf == NULL) {
6042         return A_NO_MEMORY;
6043     }
6044
6045     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
6046     cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
6047     A_MEMZERO(cmd, sizeof(*cmd));
6048
6049     cmd->period = period;
6050
6051     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
6052 }
6053
6054 int
6055 wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
6056 {
6057     WMI_AP_PROT_SCAN_TIME_CMD *cmd;
6058     void *osbuf = NULL;
6059
6060     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6061     if (osbuf == NULL) {
6062         return A_NO_MEMORY;
6063     }
6064
6065     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6066     cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
6067     A_MEMZERO(cmd, sizeof(*cmd));
6068
6069     cmd->period_min = period;
6070     cmd->dwell_ms   = dwell;
6071
6072     return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
6073 }
6074
6075 int
6076 wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
6077 {
6078     WMI_AP_SET_DTIM_CMD *cmd;
6079     void *osbuf = NULL;
6080
6081     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
6082     if (osbuf == NULL) {
6083         return A_NO_MEMORY;
6084     }
6085
6086     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
6087     cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
6088     A_MEMZERO(cmd, sizeof(*cmd));
6089
6090     cmd->dtim = dtim;
6091
6092     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
6093 }
6094
6095 /*
6096  * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
6097  *
6098  * This command is used to set ACL policay. While changing policy, if you
6099  * want to retain the existing MAC addresses in the ACL list, policy should be
6100  * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
6101  * If there is no chage in policy, the list will be intact.
6102  */
6103 int
6104 wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
6105 {
6106     void *osbuf;
6107     WMI_AP_ACL_POLICY_CMD *po;
6108
6109     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
6110     if (osbuf == NULL) {
6111         return A_NO_MEMORY;
6112 }
6113
6114     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
6115     po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
6116     A_MEMZERO(po, sizeof(*po));
6117
6118     po->policy = policy;
6119
6120     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
6121 }
6122
6123 int
6124 wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
6125 {
6126     void *osbuf;
6127     WMI_AP_SET_11BG_RATESET_CMD *rs;
6128
6129     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6130     if (osbuf == NULL) {
6131         return A_NO_MEMORY;
6132     }
6133
6134     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6135     rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
6136     A_MEMZERO(rs, sizeof(*rs));
6137
6138     rs->rateset = rateset;
6139
6140     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
6141 }
6142
6143 int
6144 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
6145 {
6146     void *osbuf;
6147     WMI_SET_HT_CAP_CMD *htCap;
6148     u8 band;
6149
6150     osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
6151     if (osbuf == NULL) {
6152         return A_NO_MEMORY;
6153     }
6154
6155     A_NETBUF_PUT(osbuf, sizeof(*htCap));
6156
6157     band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
6158     wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
6159
6160     htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
6161     A_MEMZERO(htCap, sizeof(*htCap));
6162     memcpy(htCap, cmd, sizeof(*htCap));
6163
6164     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6165                          NO_SYNC_WMIFLAG));
6166 }
6167
6168 int
6169 wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
6170 {
6171     void *osbuf;
6172     WMI_SET_HT_OP_CMD *htInfo;
6173
6174     osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
6175     if (osbuf == NULL) {
6176         return A_NO_MEMORY;
6177     }
6178
6179     A_NETBUF_PUT(osbuf, sizeof(*htInfo));
6180
6181     htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
6182     A_MEMZERO(htInfo, sizeof(*htInfo));
6183     htInfo->sta_chan_width = sta_chan_width;
6184
6185     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
6186                          NO_SYNC_WMIFLAG));
6187 }
6188
6189 int
6190 wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
6191 {
6192     void *osbuf;
6193     WMI_SET_TX_SELECT_RATES_CMD *pData;
6194
6195     osbuf = A_NETBUF_ALLOC(sizeof(*pData));
6196     if (osbuf == NULL) {
6197         return A_NO_MEMORY;
6198     }
6199
6200     A_NETBUF_PUT(osbuf, sizeof(*pData));
6201
6202     pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
6203     memcpy(pData, pMaskArray, sizeof(*pData));
6204
6205     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6206                          NO_SYNC_WMIFLAG));
6207 }
6208
6209
6210 int
6211 wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
6212 {
6213     void *osbuf;
6214     WMI_HCI_CMD *cmd;
6215
6216     osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
6217     if (osbuf == NULL) {
6218         return A_NO_MEMORY;
6219     }
6220
6221     A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
6222     cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
6223
6224     cmd->cmd_buf_sz = sz;
6225     memcpy(cmd->buf, buf, sz);
6226     return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6227 }
6228
6229 int
6230 wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
6231 {
6232     void *osbuf;
6233     WMI_ALLOW_AGGR_CMD *cmd;
6234
6235     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6236     if (osbuf == NULL) {
6237         return A_NO_MEMORY;
6238     }
6239
6240     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6241
6242     cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
6243     cmd->tx_allow_aggr = tx_tidmask;
6244     cmd->rx_allow_aggr = rx_tidmask;
6245
6246     return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
6247 }
6248
6249 int
6250 wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
6251 {
6252     void *osbuf;
6253     WMI_ADDBA_REQ_CMD *cmd;
6254
6255     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6256     if (osbuf == NULL) {
6257         return A_NO_MEMORY;
6258     }
6259
6260     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6261
6262     cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6263     cmd->tid = tid;
6264
6265     return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6266 }
6267
6268 int
6269 wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
6270 {
6271     void *osbuf;
6272     WMI_DELBA_REQ_CMD *cmd;
6273
6274     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6275     if (osbuf == NULL) {
6276         return A_NO_MEMORY;
6277     }
6278
6279     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6280
6281     cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6282     cmd->tid = tid;
6283     cmd->is_sender_initiator = uplink;  /* uplink =1 - uplink direction, 0=downlink direction */
6284
6285     /* Delete the local aggr state, on host */
6286     return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6287 }
6288
6289 int
6290 wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
6291                             bool rxDot11Hdr, bool defragOnHost)
6292 {
6293     void *osbuf;
6294     WMI_RX_FRAME_FORMAT_CMD *cmd;
6295
6296     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6297     if (osbuf == NULL) {
6298         return A_NO_MEMORY;
6299     }
6300
6301     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6302
6303     cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
6304     cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6305     cmd->defragOnHost = (defragOnHost==true)? 1:0;
6306     cmd->metaVersion = rxMetaVersion;  /*  */
6307
6308     /* Delete the local aggr state, on host */
6309     return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
6310 }
6311
6312
6313 int
6314 wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
6315 {
6316     void *osbuf;
6317     WMI_SET_THIN_MODE_CMD *cmd;
6318
6319     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6320     if (osbuf == NULL) {
6321         return A_NO_MEMORY;
6322     }
6323
6324     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6325
6326     cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
6327     cmd->enable = (bThinMode==true)? 1:0;
6328
6329     /* Delete the local aggr state, on host */
6330     return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
6331 }
6332
6333
6334 int
6335 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
6336 {
6337     void *osbuf;
6338     WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
6339
6340     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6341     if (osbuf == NULL) {
6342         return A_NO_MEMORY;
6343     }
6344
6345     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6346
6347     cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
6348     A_MEMZERO(cmd, sizeof(*cmd));
6349     cmd->precedence = precedence;
6350
6351     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
6352                          NO_SYNC_WMIFLAG));
6353 }
6354
6355 int
6356 wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
6357 {
6358     void *osbuf;
6359     WMI_SET_PMK_CMD *p;
6360
6361     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
6362     if (osbuf == NULL) {
6363         return A_NO_MEMORY;
6364     }
6365
6366     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
6367
6368     p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
6369     A_MEMZERO(p, sizeof(*p));
6370
6371     memcpy(p->pmk, pmk, WMI_PMK_LEN);
6372
6373     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6374 }
6375
6376 int
6377 wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
6378 {
6379     void *osbuf;
6380     WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
6381
6382     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6383     if (osbuf == NULL) {
6384         return A_NO_MEMORY;
6385     }
6386
6387     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6388
6389     p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
6390     memset(p, 0, sizeof(*p));
6391
6392     p->threshold = cmd->threshold;
6393
6394     return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
6395 }
6396
6397 int
6398 wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
6399 {
6400     void *osbuf;
6401     WMI_SET_TX_SGI_PARAM_CMD *cmd;
6402
6403     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6404     if (osbuf == NULL) {
6405         return A_NO_MEMORY ;
6406     }
6407
6408     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6409
6410     cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
6411     A_MEMZERO(cmd, sizeof(*cmd));
6412     cmd->sgiMask = sgiMask;
6413     cmd->sgiPERThreshold = sgiPERThreshold;
6414     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
6415                          NO_SYNC_WMIFLAG));
6416 }
6417
6418 bss_t *
6419 wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
6420                    u32 ssidLength,
6421                    u32 dot11AuthMode, u32 authMode,
6422                    u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
6423 {
6424     bss_t *node = NULL;
6425     node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
6426                                ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
6427
6428     return node;
6429 }
6430
6431 u16 wmi_ieee2freq (int chan)
6432 {
6433     u16 freq = 0;
6434     freq = wlan_ieee2freq (chan);
6435     return freq;
6436
6437 }
6438
6439 u32 wmi_freq2ieee (u16 freq)
6440 {
6441     u16 chan = 0;
6442     chan = wlan_freq2ieee (freq);
6443     return chan;
6444 }