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