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 struct 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 int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
74 
75 static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
76                                      int len);
77 static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
78                                         int len);
79 
80 static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
81                                         int len);
82 static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
83                                      int len);
84 static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
85                                        int len);
86 static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
87                                      int len);
88 static int wmi_sync_point(struct wmi_t *wmip);
89 
90 static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
91                                      int len);
92 static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
93                                      int len);
94 static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
95                                          int len);
96 static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
97                                        int len);
98 static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
99 static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
100                                              int len);
101 
102 static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
103                                      int len);
104 #ifdef CONFIG_HOST_DSET_SUPPORT
105 static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
106 static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
107                                      int len);
108 #endif /* CONFIG_HOST_DSET_SUPPORT */
109 
110 
111 static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
112                                      int len);
113 static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
114 static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
115 static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
116 static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
117 static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
118 static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
119 static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
120 static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
121                                       int len);
122 static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
123                                       int len);
124 static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
125                                       int len);
126 static int
127 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
128 
129 static int
130 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
131 
132 static int
133 wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
134 
135 #ifdef CONFIG_HOST_GPIO_SUPPORT
136 static int wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len);
137 static int wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len);
138 static int wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len);
139 #endif /* CONFIG_HOST_GPIO_SUPPORT */
140 
141 #ifdef CONFIG_HOST_TCMD_SUPPORT
142 static int
143 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
144 #endif
145 
146 static int
147 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
148 
149 static int
150 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
151 
152 static int
153 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
154 
155 static bool
156 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
157 
158 static int
159 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
160 
161 static int
162 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
163 
164 static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
165 
166 int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
167                   WMI_SYNC_FLAG syncflag);
168 
169 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
170 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 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 int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
175                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
176 static int 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 int
180 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
181 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
182 
183 static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
184                                      int len);
185 static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
186                                      int len);
187 
188 static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
189                                         int len);
190 #ifdef ATH_AR6K_11N_SUPPORT
191 static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
192 static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
193 static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
194 static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
195 static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
196 #endif
197 static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
198 
199 #ifdef WAPI_ENABLE
200 static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *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 s32 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       ((s32) 4)
248 #define MODE_A_SUPPORT_RATE_STOP        ((s32) 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       ((s32) 0)
254 #define MODE_B_SUPPORT_RATE_STOP        ((s32) 3)
255 
256 #define MODE_G_SUPPORT_RATE_START       ((s32) 0)
257 #define MODE_G_SUPPORT_RATE_STOP        ((s32) 11)
258 
259 #define MODE_GHT20_SUPPORT_RATE_START   ((s32) 0)
260 #define MODE_GHT20_SUPPORT_RATE_STOP    ((s32) 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 u8 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     u8 ip_ver_hdrlen;          /* version and hdr length */
281     u8 ip_tos;                 /* type of service */
282     u16 ip_len;                 /* total length */
283     u16 ip_id;                  /* identification */
284     s16 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     u8 ip_ttl;                 /* time to live */
289     u8 ip_p;                   /* protocol */
290     u16 ip_sum;                 /* checksum */
291     u8 ip_src[4];              /* source and dest address */
292     u8 ip_dst[4];
293 } POSTPACK iphdr;
294 
295 #include "athendpack.h"
296 
297 static s16 rssi_event_value = 0;
298 static s16 snr_event_value = 0;
299 
300 bool is_probe_ssid = false;
301 
302 void *
wmi_init(void * devt)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
wmi_qos_state_init(struct wmi_t * wmip)336 wmi_qos_state_init(struct wmi_t *wmip)
337 {
338     u8 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
wmi_set_control_ep(struct wmi_t * wmip,HTC_ENDPOINT_ID eid)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
wmi_get_control_ep(struct wmi_t * wmip)367 wmi_get_control_ep(struct wmi_t * wmip)
368 {
369     return(wmip->wmi_endpoint_id);
370 }
371 
372 void
wmi_shutdown(struct wmi_t * wmip)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 int
wmi_dix_2_dot3(struct wmi_t * wmip,void * osbuf)395 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
396 {
397     u8 *datap;
398     u16 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 = *(u16 *)(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 (0);
420     }
421 
422     /*
423      * Save mac fields and length to be inserted later
424      */
425     memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
426     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)) != 0) {
434         return A_NO_MEMORY;
435     }
436     datap = A_NETBUF_DATA(osbuf);
437 
438     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 (0);
450 }
451 
wmi_meta_add(struct wmi_t * wmip,void * osbuf,u8 * pVersion,void * pTxMetaS)452 int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
453 {
454     switch(*pVersion){
455 	case 0:
456 		return (0);
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) != 0) {
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 (0);
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) != 0) {
484             		return A_NO_MEMORY;
485         	}
486          	pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
487          	memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
488 		return (0);
489     		}
490 #endif
491 	default:
492 		return (0);
493     }
494 }
495 
496 /* Adds a WMI data header */
497 int
wmi_data_hdr_add(struct wmi_t * wmip,void * osbuf,u8 msgType,bool bMoreData,WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion,void * pTxMetaS)498 wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
499                     WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
500 {
501     WMI_DATA_HDR     *dtHdr;
502 //    u8 metaVersion = 0;
503     int 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)) != 0) {
510         return status;
511     }
512 
513     if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
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 (0);
531 }
532 
533 
wmi_implicit_create_pstream(struct wmi_t * wmip,void * osbuf,u32 layer2Priority,bool wmmEnabled)534 u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
535 {
536     u8 *datap;
537     u8 trafficClass = WMM_AC_BE;
538     u16 ipType = IP_ETHERTYPE;
539     WMI_DATA_HDR    *dtHdr;
540     u8 streamExists = 0;
541     u8 userPriority;
542     u32 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(u32));
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 (((u8 *)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 int
wmi_dot11_hdr_add(struct wmi_t * wmip,void * osbuf,NETWORK_TYPE mode)625 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
626 {
627     u8 *datap;
628     u16 typeorlen;
629     ATH_MAC_HDR      macHdr;
630     ATH_LLC_SNAP_HDR *llcHdr;
631     struct           ieee80211_frame *wh;
632     u32 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 = *(u16 *)(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     memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
658     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)) != 0) {
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(u32));
686         if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
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(u32));
696         if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
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 (0);
714 }
715 
716 int
wmi_dot11_hdr_remove(struct wmi_t * wmip,void * osbuf)717 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
718 {
719     u8 *datap;
720     struct           ieee80211_frame *pwh,wh;
721     u8 type,subtype;
722     ATH_LLC_SNAP_HDR *llcHdr;
723     ATH_MAC_HDR      macHdr;
724     u32 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     memcpy((u8 *)&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(u32));
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     memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
776 
777     return 0;
778 }
779 
780 /*
781  *  performs 802.3 to DIX encapsulation for received packets.
782  *  Assumes the entire 802.3 header is contigous.
783  */
784 int
wmi_dot3_2_dix(void * osbuf)785 wmi_dot3_2_dix(void *osbuf)
786 {
787     u8 *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     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)) != 0) {
799         return A_NO_MEMORY;
800     }
801 
802     datap = A_NETBUF_DATA(osbuf);
803 
804     memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
805 
806     return (0);
807 }
808 
809 /*
810  * Removes a WMI data header
811  */
812 int
wmi_data_hdr_remove(struct wmi_t * wmip,void * osbuf)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
wmi_iterate_nodes(struct wmi_t * wmip,wlan_node_iter_func * f,void * arg)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 int
wmi_control_rx_xtnd(struct wmi_t * wmip,void * osbuf)830 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
831 {
832     WMIX_CMD_HDR *cmd;
833     u16 id;
834     u8 *datap;
835     u32 len;
836     int status = 0;
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)) != 0) {
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 u32 cmdRecvNum;
905 
906 int
wmi_control_rx(struct wmi_t * wmip,void * osbuf)907 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
908 {
909     WMI_CMD_HDR *cmd;
910     u16 id;
911     u8 *datap;
912     u32 len, i, loggingReq;
913     int status = 0;
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)) != 0) {
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             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             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 int
wmi_simple_cmd(struct wmi_t * wmip,WMI_COMMAND_ID cmdid)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 int
wmi_simple_cmd_xtnd(struct wmi_t * wmip,WMIX_COMMAND_ID cmdid)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 int
wmi_ready_event_rx(struct wmi_t * wmip,u8 * datap,int len)1227 wmi_ready_event_rx(struct wmi_t *wmip, u8 *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 0;
1240 }
1241 
1242 #define LE_READ_4(p)                            \
1243     ((u32)                            \
1244      ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
1245       (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
1246 
1247 static int __inline
iswmmoui(const u8 * frm)1248 iswmmoui(const u8 *frm)
1249 {
1250     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1251 }
1252 
1253 static int __inline
iswmmparam(const u8 * frm)1254 iswmmparam(const u8 *frm)
1255 {
1256     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1257 }
1258 
1259 
1260 static int
wmi_connect_event_rx(struct wmi_t * wmip,u8 * datap,int len)1261 wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1262 {
1263     WMI_CONNECT_EVENT *ev;
1264     u8 *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     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(u16)  +  /* capinfo*/
1283                             sizeof(u16)  +  /* status Code */
1284                             sizeof(u16)  ;  /* 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 0;
1318 }
1319 
1320 static int
wmi_regDomain_event_rx(struct wmi_t * wmip,u8 * datap,int len)1321 wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *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 0;
1333 }
1334 
1335 static int
wmi_neighborReport_event_rx(struct wmi_t * wmip,u8 * datap,int len)1336 wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *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 0;
1354 }
1355 
1356 static int
wmi_disconnect_event_rx(struct wmi_t * wmip,u8 * datap,int len)1357 wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *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 0;
1379 }
1380 
1381 static int
wmi_peer_node_event_rx(struct wmi_t * wmip,u8 * datap,int len)1382 wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *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 0;
1399 }
1400 
1401 static int
wmi_tkip_micerr_event_rx(struct wmi_t * wmip,u8 * datap,int len)1402 wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *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 0;
1415 }
1416 
1417 static int
wmi_bssInfo_event_rx(struct wmi_t * wmip,u8 * datap,int len)1418 wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1419 {
1420     bss_t *bss = NULL;
1421     WMI_BSS_INFO_HDR *bih;
1422     u8 *buf;
1423     u32 nodeCachingAllowed = 1;
1424     u8 cached_ssid_len = 0;
1425     u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
1426     u8 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 0;  //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) != 0) {
1447         wmi_node_return(wmip, bss);
1448         return A_EINVAL;
1449     }
1450 
1451     if(!nodeCachingAllowed) {
1452         wmi_node_return(wmip, bss);
1453         return 0;
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 0;
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             u8 *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         u8 *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         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         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         memcpy(ni_buf, buf, buf_len);
1561     }
1562     else
1563         memcpy(bss->ni_buf, buf, len);
1564 
1565     bss->ni_framelen = len;
1566     if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
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 0;
1579 }
1580 
1581 static int
wmi_opt_frame_event_rx(struct wmi_t * wmip,u8 * datap,int len)1582 wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1583 {
1584     bss_t *bss;
1585     WMI_OPT_RX_INFO_HDR *bih;
1586     u8 *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     memcpy(bss->ni_buf, buf, len);
1618     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1619 
1620     return 0;
1621 }
1622 
1623     /* This event indicates inactivity timeout of a fatpipe(pstream)
1624      * at the target
1625      */
1626 static int
wmi_pstream_timeout_event_rx(struct wmi_t * wmip,u8 * datap,int len)1627 wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *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 0;
1654 }
1655 
1656 static int
wmi_bitrate_reply_rx(struct wmi_t * wmip,u8 * datap,int len)1657 wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1658 {
1659     WMI_BIT_RATE_REPLY *reply;
1660     s32 rate;
1661     u32 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 == (s8) 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 0;
1685 }
1686 
1687 static int
wmi_ratemask_reply_rx(struct wmi_t * wmip,u8 * datap,int len)1688 wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *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 0;
1702 }
1703 
1704 static int
wmi_channelList_reply_rx(struct wmi_t * wmip,u8 * datap,int len)1705 wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *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 0;
1719 }
1720 
1721 static int
wmi_txPwr_reply_rx(struct wmi_t * wmip,u8 * datap,int len)1722 wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *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 0;
1735 }
1736 static int
wmi_keepalive_reply_rx(struct wmi_t * wmip,u8 * datap,int len)1737 wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *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 0;
1750 }
1751 
1752 
1753 static int
wmi_dset_open_req_rx(struct wmi_t * wmip,u8 * datap,int len)1754 wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *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 0;
1771 }
1772 
1773 #ifdef CONFIG_HOST_DSET_SUPPORT
1774 static int
wmi_dset_close_rx(struct wmi_t * wmip,u8 * datap,int len)1775 wmi_dset_close_rx(struct wmi_t *wmip, u8 *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 0;
1788 }
1789 
1790 static int
wmi_dset_data_req_rx(struct wmi_t * wmip,u8 * datap,int len)1791 wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *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 0;
1810 }
1811 #endif /* CONFIG_HOST_DSET_SUPPORT */
1812 
1813 static int
wmi_scanComplete_rx(struct wmi_t * wmip,u8 * datap,int len)1814 wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
1815 {
1816     WMI_SCAN_COMPLETE_EVENT *ev;
1817 
1818     ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1819     if ((int)ev->status == 0) {
1820         wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1821     }
1822     A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1823     is_probe_ssid = false;
1824 
1825     return 0;
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 int
wmi_errorEvent_rx(struct wmi_t * wmip,u8 * datap,int len)1836 wmi_errorEvent_rx(struct wmi_t *wmip, u8 *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 0;
1855 }
1856 
1857 
1858 static int
wmi_statsEvent_rx(struct wmi_t * wmip,u8 * datap,int len)1859 wmi_statsEvent_rx(struct wmi_t *wmip, u8 *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 0;
1866 }
1867 
1868 static int
wmi_rssiThresholdEvent_rx(struct wmi_t * wmip,u8 * datap,int len)1869 wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *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     u8 upper_rssi_threshold, lower_rssi_threshold;
1877     s16 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) != 0) {
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 0;
1970 }
1971 
1972 
1973 static int
wmi_reportErrorEvent_rx(struct wmi_t * wmip,u8 * datap,int len)1974 wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *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 0;
1987 }
1988 
1989 static int
wmi_cac_event_rx(struct wmi_t * wmip,u8 * datap,int len)1990 wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1991 {
1992     WMI_CAC_EVENT *reply;
1993     WMM_TSPEC_IE *tspec_ie;
1994     u16 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         u8 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         u8 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 0;
2057 }
2058 
2059 static int
wmi_channel_change_event_rx(struct wmi_t * wmip,u8 * datap,int len)2060 wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *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 0;
2074 }
2075 
2076 static int
wmi_hbChallengeResp_rx(struct wmi_t * wmip,u8 * datap,int len)2077 wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *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 0;
2090 }
2091 
2092 static int
wmi_roam_tbl_event_rx(struct wmi_t * wmip,u8 * datap,int len)2093 wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *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 0;
2106 }
2107 
2108 static int
wmi_roam_data_event_rx(struct wmi_t * wmip,u8 * datap,int len)2109 wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *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 0;
2122 }
2123 
2124 static int
wmi_txRetryErrEvent_rx(struct wmi_t * wmip,u8 * datap,int len)2125 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *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 0;
2135 }
2136 
2137 static int
wmi_snrThresholdEvent_rx(struct wmi_t * wmip,u8 * datap,int len)2138 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *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     u8 upper_snr_threshold, lower_snr_threshold;
2146     s16 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) != 0) {
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 0;
2228 }
2229 
2230 static int
wmi_lqThresholdEvent_rx(struct wmi_t * wmip,u8 * datap,int len)2231 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *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 0;
2246 }
2247 
2248 static int
wmi_aplistEvent_rx(struct wmi_t * wmip,u8 * datap,int len)2249 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2250 {
2251     u16 ap_info_entry_size;
2252     WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2253     WMI_AP_INFO_V1 *ap_info_v1;
2254     u8 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 0;
2287 }
2288 
2289 static int
wmi_dbglog_event_rx(struct wmi_t * wmip,u8 * datap,int len)2290 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2291 {
2292     u32 dropped;
2293 
2294     dropped = *((u32 *)datap);
2295     datap += sizeof(dropped);
2296     len -= sizeof(dropped);
2297     A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
2298     return 0;
2299 }
2300 
2301 #ifdef CONFIG_HOST_GPIO_SUPPORT
2302 static int
wmi_gpio_intr_rx(struct wmi_t * wmip,u8 * datap,int len)2303 wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *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 0;
2314 }
2315 
2316 static int
wmi_gpio_data_rx(struct wmi_t * wmip,u8 * datap,int len)2317 wmi_gpio_data_rx(struct wmi_t *wmip, u8 *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 0;
2328 }
2329 
2330 static int
wmi_gpio_ack_rx(struct wmi_t * wmip,u8 * datap,int len)2331 wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len)
2332 {
2333     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2334 
2335     A_WMI_GPIO_ACK_RX();
2336 
2337     return 0;
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 int
wmi_cmd_send(struct wmi_t * wmip,void * osbuf,WMI_COMMAND_ID cmdId,WMI_SYNC_FLAG syncflag)2346 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2347                WMI_SYNC_FLAG syncflag)
2348 {
2349     int 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)) != 0) {
2370         A_NETBUF_FREE(osbuf);
2371         return A_NO_MEMORY;
2372     }
2373 
2374     cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
2375     cHdr->commandId = (u16) 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)) != 0) {
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 (0);
2398 #undef IS_OPT_TX_CMD
2399 }
2400 
2401 int
wmi_cmd_send_xtnd(struct wmi_t * wmip,void * osbuf,WMIX_COMMAND_ID cmdId,WMI_SYNC_FLAG syncflag)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)) != 0) {
2408         A_NETBUF_FREE(osbuf);
2409         return A_NO_MEMORY;
2410     }
2411 
2412     cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
2413     cHdr->commandId = (u32) cmdId;
2414 
2415     return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2416 }
2417 
2418 int
wmi_connect_cmd(struct wmi_t * wmip,NETWORK_TYPE netType,DOT11_AUTH_MODE dot11AuthMode,AUTH_MODE authMode,CRYPTO_TYPE pairwiseCrypto,u8 pairwiseCryptoLen,CRYPTO_TYPE groupCrypto,u8 groupCryptoLen,int ssidLength,u8 * ssid,u8 * bssid,u16 channel,u32 ctrl_flags)2419 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2420                 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
2421                 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2422                 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
2423                 int ssidLength, u8 *ssid,
2424                 u8 *bssid, u16 channel, u32 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         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         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 int
wmi_reconnect_cmd(struct wmi_t * wmip,u8 * bssid,u16 channel)2474 wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 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         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 int
wmi_disconnect_cmd(struct wmi_t * wmip)2500 wmi_disconnect_cmd(struct wmi_t *wmip)
2501 {
2502     int 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 int
wmi_startscan_cmd(struct wmi_t * wmip,WMI_SCAN_TYPE scanType,u32 forceFgScan,u32 isLegacy,u32 homeDwellTime,u32 forceScanInterval,s8 numChan,u16 * channelList)2513 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
2514                   u32 forceFgScan, u32 isLegacy,
2515                   u32 homeDwellTime, u32 forceScanInterval,
2516                   s8 numChan, u16 *channelList)
2517 {
2518     void *osbuf;
2519     WMI_START_SCAN_CMD *sc;
2520     s8 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(u16) * (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         memcpy(sc->channelList, channelList, numChan * sizeof(u16));
2551     }
2552 
2553     return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2554 }
2555 
2556 int
wmi_scanparams_cmd(struct wmi_t * wmip,u16 fg_start_sec,u16 fg_end_sec,u16 bg_sec,u16 minact_chdw_msec,u16 maxact_chdw_msec,u16 pas_chdw_msec,u8 shScanRatio,u8 scanCtrlFlags,u32 max_dfsch_act_time,u16 maxact_scan_per_ssid)2557 wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
2558                    u16 fg_end_sec, u16 bg_sec,
2559                    u16 minact_chdw_msec, u16 maxact_chdw_msec,
2560                    u16 pas_chdw_msec,
2561                    u8 shScanRatio, u8 scanCtrlFlags,
2562                    u32 max_dfsch_act_time, u16 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 int
wmi_bssfilter_cmd(struct wmi_t * wmip,u8 filter,u32 ieMask)2592 wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 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 int
wmi_probedSsid_cmd(struct wmi_t * wmip,u8 index,u8 flag,u8 ssidLength,u8 * ssid)2618 wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
2619                    u8 ssidLength, u8 *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     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 int
wmi_listeninterval_cmd(struct wmi_t * wmip,u16 listenInterval,u16 listenBeacons)2660 wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 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 int
wmi_bmisstime_cmd(struct wmi_t * wmip,u16 bmissTime,u16 bmissBeacons)2682 wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 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 int
wmi_associnfo_cmd(struct wmi_t * wmip,u8 ieType,u8 ieLen,u8 * ieInfo)2704 wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2705                      u8 ieLen, u8 *ieInfo)
2706 {
2707     void *osbuf;
2708     WMI_SET_ASSOC_INFO_CMD *cmd;
2709     u16 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     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 int
wmi_powermode_cmd(struct wmi_t * wmip,u8 powerMode)2730 wmi_powermode_cmd(struct wmi_t *wmip, u8 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 int
wmi_ibsspmcaps_cmd(struct wmi_t * wmip,u8 pmEnable,u8 ttl,u16 atim_windows,u16 timeout_value)2752 wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
2753                    u16 atim_windows, u16 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 int
wmi_apps_cmd(struct wmi_t * wmip,u8 psType,u32 idle_time,u32 ps_period,u8 sleep_period)2777 wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2778                    u32 ps_period, u8 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 int
wmi_pmparams_cmd(struct wmi_t * wmip,u16 idlePeriod,u16 psPollNum,u16 dtimPolicy,u16 tx_wakeup_policy,u16 num_tx_to_wakeup,u16 ps_fail_event_policy)2802 wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
2803                  u16 psPollNum, u16 dtimPolicy,
2804                  u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2805                  u16 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 int
wmi_disctimeout_cmd(struct wmi_t * wmip,u8 timeout)2831 wmi_disctimeout_cmd(struct wmi_t *wmip, u8 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 int
wmi_addKey_cmd(struct wmi_t * wmip,u8 keyIndex,CRYPTO_TYPE keyType,u8 keyUsage,u8 keyLength,u8 * keyRSC,u8 * keyMaterial,u8 key_op_ctrl,u8 * macAddr,WMI_SYNC_FLAG sync_flag)2852 wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
2853                u8 keyUsage, u8 keyLength, u8 *keyRSC,
2854                u8 *keyMaterial, u8 key_op_ctrl, u8 *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     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         memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
2890     }
2891     cmd->key_op_ctrl = key_op_ctrl;
2892 
2893     if(macAddr) {
2894         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 int
2901 wmi_add_krk_cmd(struct wmi_t *wmip, u8 *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     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 int
2921 wmi_delete_krk_cmd(struct wmi_t *wmip)
2922 {
2923     return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2924 }
2925 
2926 int
2927 wmi_deleteKey_cmd(struct wmi_t *wmip, u8 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 int
2952 wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
2953                  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     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
2975     if (set == true) {
2976         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 int
2987 wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, 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 int
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 int
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     u16 cmdLen;
3033     u8 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         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 int
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 int
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)) != 0) {
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     u8 trafficClass;
3085     void               *osbuf;
3086 }WMI_DATA_SYNC_BUFS;
3087 
3088 static int
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     u8 i,numPriStreams=0;
3095     int status = 0;
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 (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 (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 (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 int
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     u8 fatPipeExistsForAC=0;
3204     s32 minimalPHY = 0;
3205     s32 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     memcpy(cmd, params, sizeof(*cmd));
3262 
3263         /* this is an implicitly created Fat pipe */
3264     if ((u32)params->tsid == (u32)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 int
3295 wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
3296 {
3297     void *osbuf;
3298     WMI_DELETE_PSTREAM_CMD *cmd;
3299     int status;
3300     u16 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 int
3359 wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
3360 {
3361     void *osbuf;
3362     WMI_FRAME_RATES_CMD *cmd;
3363     u8 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 = (u8)((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 int
3398 wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
3399 {
3400     void *osbuf;
3401     WMI_BIT_RATE_CMD *cmd;
3402     s8 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 int
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 bool
3457 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
3458 {
3459     WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
3460     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 s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
3513 {
3514     s8 i;
3515 
3516     for (i=0;;i++)
3517     {
3518         if (wmi_rateTable[(u32) i][0] == 0) {
3519             return A_EINVAL;
3520         }
3521         if (wmi_rateTable[(u32) i][0] == rate) {
3522             break;
3523         }
3524     }
3525 
3526     if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
3527         return A_EINVAL;
3528     }
3529 
3530     *rate_idx = i;
3531     return 0;
3532 }
3533 
3534 int
3535 wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
3536 {
3537     void *osbuf;
3538     WMI_FIX_RATES_CMD *cmd;
3539 #if 0
3540     s32 rateIndex;
3541 /* This check does not work for AR6003 as the HT modes are enabled only when
3542  * the STA is connected to a HT_BSS and is not based only on channel. It is
3543  * safe to skip this check however because rate control will only use rates
3544  * that are permitted by the valid rate mask and the fix rate mask. Meaning
3545  * the fix rate mask is not sufficient by itself to cause an invalid rate
3546  * to be used. */
3547     /* Make sure all rates in the mask are valid in the current PHY mode */
3548     for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
3549        if((1 << rateIndex) & (u32)fixRatesMask) {
3550             if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
3551                 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
3552                 return A_EINVAL;
3553             }
3554        }
3555     }
3556 #endif
3557 
3558 
3559     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3560     if (osbuf == NULL) {
3561         return A_NO_MEMORY;
3562     }
3563 
3564     A_NETBUF_PUT(osbuf, sizeof(*cmd));
3565 
3566     cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3567     A_MEMZERO(cmd, sizeof(*cmd));
3568 
3569     cmd->fixRateMask = fixRatesMask;
3570 
3571     return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
3572 }
3573 
3574 int
3575 wmi_get_ratemask_cmd(struct wmi_t *wmip)
3576 {
3577     return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3578 }
3579 
3580 int
3581 wmi_get_channelList_cmd(struct wmi_t *wmip)
3582 {
3583     return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
3584 }
3585 
3586 /*
3587  * used to generate a wmi sey channel Parameters cmd.
3588  * mode should always be specified and corresponds to the phy mode of the
3589  * wlan.
3590  * numChan should alway sbe specified. If zero indicates that all available
3591  * channels should be used.
3592  * channelList is an array of channel frequencies (in Mhz) which the radio
3593  * should limit its operation to.  It should be NULL if numChan == 0.  Size of
3594  * array should correspond to numChan entries.
3595  */
3596 int
3597 wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
3598                           WMI_PHY_MODE mode, s8 numChan,
3599                           u16 *channelList)
3600 {
3601     void *osbuf;
3602     WMI_CHANNEL_PARAMS_CMD *cmd;
3603     s8 size;
3604 
3605     size = sizeof (*cmd);
3606 
3607     if (numChan) {
3608         if (numChan > WMI_MAX_CHANNELS) {
3609             return A_EINVAL;
3610         }
3611         size += sizeof(u16) * (numChan - 1);
3612     }
3613 
3614     osbuf = A_NETBUF_ALLOC(size);
3615     if (osbuf == NULL) {
3616         return A_NO_MEMORY;
3617     }
3618 
3619     A_NETBUF_PUT(osbuf, size);
3620 
3621     cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3622     A_MEMZERO(cmd, size);
3623 
3624     wmip->wmi_phyMode = mode;
3625     cmd->scanParam   = scanParam;
3626     cmd->phyMode     = mode;
3627     cmd->numChannels = numChan;
3628     memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
3629 
3630     return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3631                          NO_SYNC_WMIFLAG));
3632 }
3633 
3634 void
3635 wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3636 {
3637     SQ_THRESHOLD_PARAMS *sq_thresh =
3638            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
3639     /*
3640      * Parse the command and store the threshold values here. The checks
3641      * for valid values can be put here
3642      */
3643     sq_thresh->weight = rssiCmd->weight;
3644     sq_thresh->polling_interval = rssiCmd->pollTime;
3645 
3646     sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3647     sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3648     sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3649     sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3650     sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3651     sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3652     sq_thresh->upper_threshold_valid_count = 6;
3653 
3654     /* List sorted in descending order */
3655     sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3656     sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3657     sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3658     sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3659     sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3660     sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3661     sq_thresh->lower_threshold_valid_count = 6;
3662 
3663     if (!rssi_event_value) {
3664     /*
3665      * Configuring the thresholds to their extremes allows the host to get an
3666      * event from the target which is used for the configuring the correct
3667      * thresholds
3668      */
3669     rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
3670     rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
3671     } else {
3672         /*
3673          * In case the user issues multiple times of rssi_threshold_setting,
3674          * we should not use the extreames anymore, the target does not expect that.
3675          */
3676         rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
3677                                               sq_thresh->upper_threshold_valid_count);
3678         rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
3679                                               sq_thresh->lower_threshold_valid_count);
3680 }
3681 }
3682 
3683 int
3684 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
3685                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3686 {
3687 
3688      /* Check these values are in ascending order */
3689     if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
3690         rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
3691         rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
3692         rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
3693         rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
3694         rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
3695         rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
3696         rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
3697         rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
3698         rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
3699     {
3700         return A_EINVAL;
3701     }
3702 
3703     wmi_cache_configure_rssithreshold(wmip, rssiCmd);
3704 
3705     return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
3706 }
3707 
3708 int
3709 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
3710 {
3711     void    *osbuf;
3712     WMI_SET_IP_CMD *cmd;
3713 
3714     /* Multicast address are not valid */
3715     if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3716        (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
3717         return A_EINVAL;
3718     }
3719 
3720     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
3721     if (osbuf == NULL) {
3722         return A_NO_MEMORY;
3723     }
3724 
3725     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
3726     cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
3727     memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
3728 
3729     return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3730                             NO_SYNC_WMIFLAG));
3731 }
3732 
3733 int
3734 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3735                               WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3736 {
3737     void    *osbuf;
3738     s8 size;
3739     WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
3740     u16 activeTsids=0;
3741     u8 streamExists=0;
3742     u8 i;
3743 
3744     if( hostModeCmd->awake == hostModeCmd->asleep) {
3745         return A_EINVAL;
3746     }
3747 
3748     size = sizeof (*cmd);
3749 
3750     osbuf = A_NETBUF_ALLOC(size);
3751     if (osbuf == NULL) {
3752         return A_NO_MEMORY;
3753     }
3754 
3755     A_NETBUF_PUT(osbuf, size);
3756 
3757     cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3758     A_MEMZERO(cmd, size);
3759     memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
3760 
3761     if(hostModeCmd->asleep) {
3762         /*
3763          * Relinquish credits from all implicitly created pstreams since when we
3764          * go to sleep. If user created explicit thinstreams exists with in a
3765          * fatpipe leave them intact for the user to delete
3766          */
3767         LOCK_WMI(wmip);
3768         streamExists = wmip->wmi_fatPipeExists;
3769         UNLOCK_WMI(wmip);
3770 
3771         for(i=0;i< WMM_NUM_AC;i++) {
3772             if (streamExists & (1<<i)) {
3773                 LOCK_WMI(wmip);
3774                 activeTsids = wmip->wmi_streamExistsForAC[i];
3775                 UNLOCK_WMI(wmip);
3776                 /* If there are no user created thin streams delete the fatpipe */
3777                 if(!activeTsids) {
3778                     streamExists &= ~(1<<i);
3779                     /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
3780                     A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
3781                 }
3782             }
3783         }
3784 
3785         /* Update the fatpipes that exists*/
3786         LOCK_WMI(wmip);
3787         wmip->wmi_fatPipeExists = streamExists;
3788         UNLOCK_WMI(wmip);
3789     }
3790 
3791     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
3792                             NO_SYNC_WMIFLAG));
3793 }
3794 
3795 int
3796 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3797                               WMI_SET_WOW_MODE_CMD *wowModeCmd)
3798 {
3799     void    *osbuf;
3800     s8 size;
3801     WMI_SET_WOW_MODE_CMD *cmd;
3802 
3803     size = sizeof (*cmd);
3804 
3805     osbuf = A_NETBUF_ALLOC(size);
3806     if (osbuf == NULL) {
3807         return A_NO_MEMORY;
3808     }
3809 
3810     A_NETBUF_PUT(osbuf, size);
3811 
3812     cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3813     A_MEMZERO(cmd, size);
3814     memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
3815 
3816     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3817                             NO_SYNC_WMIFLAG));
3818 
3819 }
3820 
3821 int
3822 wmi_get_wow_list_cmd(struct wmi_t *wmip,
3823                               WMI_GET_WOW_LIST_CMD *wowListCmd)
3824 {
3825     void    *osbuf;
3826     s8 size;
3827     WMI_GET_WOW_LIST_CMD *cmd;
3828 
3829     size = sizeof (*cmd);
3830 
3831     osbuf = A_NETBUF_ALLOC(size);
3832     if (osbuf == NULL) {
3833         return A_NO_MEMORY;
3834     }
3835 
3836     A_NETBUF_PUT(osbuf, size);
3837 
3838     cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
3839     A_MEMZERO(cmd, size);
3840     memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
3841 
3842     return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3843                             NO_SYNC_WMIFLAG));
3844 
3845 }
3846 
3847 static int
3848 wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
3849 {
3850     WMI_GET_WOW_LIST_REPLY *reply;
3851 
3852     if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
3853         return A_EINVAL;
3854     }
3855     reply = (WMI_GET_WOW_LIST_REPLY *)datap;
3856 
3857     A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
3858                           reply);
3859 
3860     return 0;
3861 }
3862 
3863 int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
3864                                  WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
3865                                  u8 *pattern, u8 *mask,
3866                                  u8 pattern_size)
3867 {
3868     void    *osbuf;
3869     s8 size;
3870     WMI_ADD_WOW_PATTERN_CMD *cmd;
3871     u8 *filter_mask = NULL;
3872 
3873     size = sizeof (*cmd);
3874 
3875     size += ((2 * addWowCmd->filter_size)* sizeof(u8));
3876     osbuf = A_NETBUF_ALLOC(size);
3877     if (osbuf == NULL) {
3878         return A_NO_MEMORY;
3879     }
3880 
3881     A_NETBUF_PUT(osbuf, size);
3882 
3883     cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3884     cmd->filter_list_id = addWowCmd->filter_list_id;
3885     cmd->filter_offset = addWowCmd->filter_offset;
3886     cmd->filter_size = addWowCmd->filter_size;
3887 
3888     memcpy(cmd->filter, pattern, addWowCmd->filter_size);
3889 
3890     filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
3891     memcpy(filter_mask, mask, addWowCmd->filter_size);
3892 
3893 
3894     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3895                             NO_SYNC_WMIFLAG));
3896 }
3897 
3898 int
3899 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3900                               WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3901 {
3902     void    *osbuf;
3903     s8 size;
3904     WMI_DEL_WOW_PATTERN_CMD *cmd;
3905 
3906     size = sizeof (*cmd);
3907 
3908     osbuf = A_NETBUF_ALLOC(size);
3909     if (osbuf == NULL) {
3910         return A_NO_MEMORY;
3911     }
3912 
3913     A_NETBUF_PUT(osbuf, size);
3914 
3915     cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3916     A_MEMZERO(cmd, size);
3917     memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
3918 
3919     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3920                             NO_SYNC_WMIFLAG));
3921 
3922 }
3923 
3924 void
3925 wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3926 {
3927     SQ_THRESHOLD_PARAMS *sq_thresh =
3928            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
3929     /*
3930      * Parse the command and store the threshold values here. The checks
3931      * for valid values can be put here
3932      */
3933     sq_thresh->weight = snrCmd->weight;
3934     sq_thresh->polling_interval = snrCmd->pollTime;
3935 
3936     sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
3937     sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
3938     sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
3939     sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
3940     sq_thresh->upper_threshold_valid_count = 4;
3941 
3942     /* List sorted in descending order */
3943     sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
3944     sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
3945     sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
3946     sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
3947     sq_thresh->lower_threshold_valid_count = 4;
3948 
3949     if (!snr_event_value) {
3950     /*
3951      * Configuring the thresholds to their extremes allows the host to get an
3952      * event from the target which is used for the configuring the correct
3953      * thresholds
3954      */
3955     snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3956     snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
3957     } else {
3958         /*
3959          * In case the user issues multiple times of snr_threshold_setting,
3960          * we should not use the extreames anymore, the target does not expect that.
3961          */
3962         snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
3963                                               sq_thresh->upper_threshold_valid_count);
3964         snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
3965                                               sq_thresh->lower_threshold_valid_count);
3966     }
3967 
3968 }
3969 int
3970 wmi_set_snr_threshold_params(struct wmi_t *wmip,
3971                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3972 {
3973     if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
3974         snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
3975         snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
3976         snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
3977         snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
3978         snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
3979     {
3980         return A_EINVAL;
3981     }
3982     wmi_cache_configure_snrthreshold(wmip, snrCmd);
3983     return (wmi_send_snr_threshold_params(wmip, snrCmd));
3984 }
3985 
3986 int
3987 wmi_clr_rssi_snr(struct wmi_t *wmip)
3988 {
3989     void    *osbuf;
3990 
3991     osbuf = A_NETBUF_ALLOC(sizeof(int));
3992     if (osbuf == NULL) {
3993         return A_NO_MEMORY;
3994     }
3995 
3996     return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
3997                             NO_SYNC_WMIFLAG));
3998 }
3999 
4000 int
4001 wmi_set_lq_threshold_params(struct wmi_t *wmip,
4002                              WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
4003 {
4004     void    *osbuf;
4005     s8 size;
4006     WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
4007     /* These values are in ascending order */
4008     if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
4009         lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
4010         lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
4011         lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
4012         lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
4013         lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
4014 
4015         return A_EINVAL;
4016     }
4017 
4018     size = sizeof (*cmd);
4019 
4020     osbuf = A_NETBUF_ALLOC(size);
4021     if (osbuf == NULL) {
4022         return A_NO_MEMORY;
4023     }
4024 
4025     A_NETBUF_PUT(osbuf, size);
4026 
4027     cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4028     A_MEMZERO(cmd, size);
4029     memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
4030 
4031     return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
4032                             NO_SYNC_WMIFLAG));
4033 }
4034 
4035 int
4036 wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
4037 {
4038     void    *osbuf;
4039     s8 size;
4040     WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
4041 
4042     size = sizeof (*cmd);
4043 
4044     osbuf = A_NETBUF_ALLOC(size);
4045     if (osbuf == NULL) {
4046         return A_NO_MEMORY;
4047     }
4048 
4049     A_NETBUF_PUT(osbuf, size);
4050 
4051     cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
4052     A_MEMZERO(cmd, size);
4053 
4054     cmd->bitmask = mask;
4055 
4056     return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
4057                             NO_SYNC_WMIFLAG));
4058 }
4059 
4060 int
4061 wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
4062 {
4063     void *osbuf;
4064     WMIX_HB_CHALLENGE_RESP_CMD *cmd;
4065 
4066     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4067     if (osbuf == NULL) {
4068         return A_NO_MEMORY;
4069     }
4070 
4071     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4072 
4073     cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
4074     cmd->cookie = cookie;
4075     cmd->source = source;
4076 
4077     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
4078                               NO_SYNC_WMIFLAG));
4079 }
4080 
4081 int
4082 wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
4083                             u16 tsr, bool rep, u16 size,
4084                             u32 valid)
4085 {
4086     void *osbuf;
4087     WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
4088 
4089     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4090     if (osbuf == NULL) {
4091         return A_NO_MEMORY;
4092     }
4093 
4094     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4095 
4096     cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
4097     cmd->config.cfgmmask = mmask;
4098     cmd->config.cfgtsr = tsr;
4099     cmd->config.cfgrep = rep;
4100     cmd->config.cfgsize = size;
4101     cmd->config.cfgvalid = valid;
4102 
4103     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
4104                               NO_SYNC_WMIFLAG));
4105 }
4106 
4107 int
4108 wmi_get_stats_cmd(struct wmi_t *wmip)
4109 {
4110     return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4111 }
4112 
4113 int
4114 wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
4115 {
4116     void *osbuf;
4117     WMI_ADD_BAD_AP_CMD *cmd;
4118 
4119     if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
4120         return A_EINVAL;
4121     }
4122 
4123     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4124     if (osbuf == NULL) {
4125         return A_NO_MEMORY;
4126     }
4127 
4128     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4129 
4130     cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4131     cmd->badApIndex = apIndex;
4132     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4133 
4134     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4135 }
4136 
4137 int
4138 wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
4139 {
4140     void *osbuf;
4141     WMI_DELETE_BAD_AP_CMD *cmd;
4142 
4143     if (apIndex > WMI_MAX_BAD_AP_INDEX) {
4144         return A_EINVAL;
4145     }
4146 
4147     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4148     if (osbuf == NULL) {
4149         return A_NO_MEMORY;
4150     }
4151 
4152     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4153 
4154     cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4155     cmd->badApIndex = apIndex;
4156 
4157     return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
4158                          NO_SYNC_WMIFLAG));
4159 }
4160 
4161 int
4162 wmi_abort_scan_cmd(struct wmi_t *wmip)
4163 {
4164     return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4165 }
4166 
4167 int
4168 wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
4169 {
4170     void *osbuf;
4171     WMI_SET_TX_PWR_CMD *cmd;
4172 
4173     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4174     if (osbuf == NULL) {
4175         return A_NO_MEMORY;
4176     }
4177 
4178     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4179 
4180     cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
4181     cmd->dbM = dbM;
4182 
4183     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
4184 }
4185 
4186 int
4187 wmi_get_txPwr_cmd(struct wmi_t *wmip)
4188 {
4189     return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4190 }
4191 
4192 u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
4193 {
4194     u16 activeTsids=0;
4195 
4196     LOCK_WMI(wmip);
4197     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4198     UNLOCK_WMI(wmip);
4199 
4200     return activeTsids;
4201 }
4202 
4203 int
4204 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4205 {
4206     return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4207 }
4208 
4209 int
4210 wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
4211 {
4212     void *osbuf;
4213     u32 size = sizeof(u8);
4214     WMI_TARGET_ROAM_DATA *cmd;
4215 
4216     osbuf = A_NETBUF_ALLOC(size);      /* no payload */
4217     if (osbuf == NULL) {
4218         return A_NO_MEMORY;
4219     }
4220 
4221     A_NETBUF_PUT(osbuf, size);
4222 
4223     cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
4224     cmd->roamDataType = roamDataType;
4225 
4226     return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
4227                          NO_SYNC_WMIFLAG));
4228 }
4229 
4230 int
4231 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
4232                       u8 size)
4233 {
4234     void *osbuf;
4235     WMI_SET_ROAM_CTRL_CMD *cmd;
4236 
4237     osbuf = A_NETBUF_ALLOC(size);
4238     if (osbuf == NULL) {
4239         return A_NO_MEMORY;
4240     }
4241 
4242     A_NETBUF_PUT(osbuf, size);
4243 
4244     cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
4245     A_MEMZERO(cmd, size);
4246 
4247     memcpy(cmd, p, size);
4248 
4249     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4250                          NO_SYNC_WMIFLAG));
4251 }
4252 
4253 int
4254 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4255                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
4256                             u8 size)
4257 {
4258     void *osbuf;
4259     WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
4260 
4261     /* These timers can't be zero */
4262     if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
4263        !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
4264          pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
4265        !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
4266          pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
4267         return A_EINVAL;
4268 
4269     osbuf = A_NETBUF_ALLOC(size);
4270     if (osbuf == NULL) {
4271         return A_NO_MEMORY;
4272     }
4273 
4274     A_NETBUF_PUT(osbuf, size);
4275 
4276     cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
4277     A_MEMZERO(cmd, size);
4278 
4279     memcpy(cmd, pCmd, size);
4280 
4281     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
4282                          NO_SYNC_WMIFLAG));
4283 }
4284 
4285 #ifdef CONFIG_HOST_GPIO_SUPPORT
4286 /* Send a command to Target to change GPIO output pins. */
4287 int
4288 wmi_gpio_output_set(struct wmi_t *wmip,
4289                     u32 set_mask,
4290                     u32 clear_mask,
4291                     u32 enable_mask,
4292                     u32 disable_mask)
4293 {
4294     void *osbuf;
4295     WMIX_GPIO_OUTPUT_SET_CMD *output_set;
4296     int size;
4297 
4298     size = sizeof(*output_set);
4299 
4300     A_DPRINTF(DBG_WMI,
4301         (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG,
4302         set_mask, clear_mask, enable_mask, disable_mask));
4303 
4304     osbuf = A_NETBUF_ALLOC(size);
4305     if (osbuf == NULL) {
4306         return A_NO_MEMORY;
4307     }
4308     A_NETBUF_PUT(osbuf, size);
4309     output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf));
4310 
4311     output_set->set_mask                   = set_mask;
4312     output_set->clear_mask                 = clear_mask;
4313     output_set->enable_mask                = enable_mask;
4314     output_set->disable_mask               = disable_mask;
4315 
4316     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID,
4317                              NO_SYNC_WMIFLAG));
4318 }
4319 
4320 /* Send a command to the Target requesting state of the GPIO input pins */
4321 int
4322 wmi_gpio_input_get(struct wmi_t *wmip)
4323 {
4324     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4325 
4326     return wmi_simple_cmd_xtnd(wmip, WMIX_GPIO_INPUT_GET_CMDID);
4327 }
4328 
4329 /* Send a command to the Target that changes the value of a GPIO register. */
4330 int
4331 wmi_gpio_register_set(struct wmi_t *wmip,
4332                       u32 gpioreg_id,
4333                       u32 value)
4334 {
4335     void *osbuf;
4336     WMIX_GPIO_REGISTER_SET_CMD *register_set;
4337     int size;
4338 
4339     size = sizeof(*register_set);
4340 
4341     A_DPRINTF(DBG_WMI,
4342         (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value));
4343 
4344     osbuf = A_NETBUF_ALLOC(size);
4345     if (osbuf == NULL) {
4346         return A_NO_MEMORY;
4347     }
4348     A_NETBUF_PUT(osbuf, size);
4349     register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf));
4350 
4351     register_set->gpioreg_id               = gpioreg_id;
4352     register_set->value                    = value;
4353 
4354     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID,
4355                              NO_SYNC_WMIFLAG));
4356 }
4357 
4358 /* Send a command to the Target to fetch the value of a GPIO register. */
4359 int
4360 wmi_gpio_register_get(struct wmi_t *wmip,
4361                       u32 gpioreg_id)
4362 {
4363     void *osbuf;
4364     WMIX_GPIO_REGISTER_GET_CMD *register_get;
4365     int size;
4366 
4367     size = sizeof(*register_get);
4368 
4369     A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id));
4370 
4371     osbuf = A_NETBUF_ALLOC(size);
4372     if (osbuf == NULL) {
4373         return A_NO_MEMORY;
4374     }
4375     A_NETBUF_PUT(osbuf, size);
4376     register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf));
4377 
4378     register_get->gpioreg_id               = gpioreg_id;
4379 
4380     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID,
4381                              NO_SYNC_WMIFLAG));
4382 }
4383 
4384 /* Send a command to the Target acknowledging some GPIO interrupts. */
4385 int
4386 wmi_gpio_intr_ack(struct wmi_t *wmip,
4387                   u32 ack_mask)
4388 {
4389     void *osbuf;
4390     WMIX_GPIO_INTR_ACK_CMD *intr_ack;
4391     int size;
4392 
4393     size = sizeof(*intr_ack);
4394 
4395     A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask));
4396 
4397     osbuf = A_NETBUF_ALLOC(size);
4398     if (osbuf == NULL) {
4399         return A_NO_MEMORY;
4400     }
4401     A_NETBUF_PUT(osbuf, size);
4402     intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf));
4403 
4404     intr_ack->ack_mask               = ack_mask;
4405 
4406     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID,
4407                              NO_SYNC_WMIFLAG));
4408 }
4409 #endif /* CONFIG_HOST_GPIO_SUPPORT */
4410 
4411 int
4412 wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac,  u16 txop, u8 eCWmin,
4413                           u8 eCWmax, u8 aifsn)
4414 {
4415     void *osbuf;
4416     WMI_SET_ACCESS_PARAMS_CMD *cmd;
4417 
4418     if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
4419         (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
4420     {
4421         return A_EINVAL;
4422     }
4423 
4424     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4425     if (osbuf == NULL) {
4426         return A_NO_MEMORY;
4427     }
4428 
4429     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4430 
4431     cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4432     cmd->txop   = txop;
4433     cmd->eCWmin = eCWmin;
4434     cmd->eCWmax = eCWmax;
4435     cmd->aifsn  = aifsn;
4436     cmd->ac = ac;
4437 
4438     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
4439                          NO_SYNC_WMIFLAG));
4440 }
4441 
4442 int
4443 wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4444                          u8 trafficClass, u8 maxRetries,
4445                          u8 enableNotify)
4446 {
4447     void *osbuf;
4448     WMI_SET_RETRY_LIMITS_CMD *cmd;
4449 
4450     if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
4451         (frameType != DATA_FRAMETYPE))
4452     {
4453         return A_EINVAL;
4454     }
4455 
4456     if (maxRetries > WMI_MAX_RETRIES) {
4457         return A_EINVAL;
4458     }
4459 
4460     if (frameType != DATA_FRAMETYPE) {
4461         trafficClass = 0;
4462     }
4463 
4464     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4465     if (osbuf == NULL) {
4466         return A_NO_MEMORY;
4467     }
4468 
4469     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4470 
4471     cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
4472     cmd->frameType    = frameType;
4473     cmd->trafficClass = trafficClass;
4474     cmd->maxRetries   = maxRetries;
4475     cmd->enableNotify = enableNotify;
4476 
4477     return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
4478                          NO_SYNC_WMIFLAG));
4479 }
4480 
4481 void
4482 wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
4483 {
4484     if (bssid != NULL) {
4485         memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
4486     }
4487 }
4488 
4489 int
4490 wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
4491 {
4492     void *osbuf;
4493     WMI_SET_OPT_MODE_CMD *cmd;
4494 
4495     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4496     if (osbuf == NULL) {
4497         return A_NO_MEMORY;
4498     }
4499 
4500     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4501 
4502     cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4503     A_MEMZERO(cmd, sizeof(*cmd));
4504     cmd->optMode = optMode;
4505 
4506     return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
4507                          SYNC_BOTH_WMIFLAG));
4508 }
4509 
4510 int
4511 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
4512                       u8 frmType,
4513                       u8 *dstMacAddr,
4514                       u8 *bssid,
4515                       u16 optIEDataLen,
4516                       u8 *optIEData)
4517 {
4518     void *osbuf;
4519     WMI_OPT_TX_FRAME_CMD *cmd;
4520     osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
4521     if (osbuf == NULL) {
4522         return A_NO_MEMORY;
4523     }
4524 
4525     A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
4526 
4527     cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
4528     A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
4529 
4530     cmd->frmType    = frmType;
4531     cmd->optIEDataLen   = optIEDataLen;
4532     //cmd->optIEData     = (u8 *)((int)cmd + sizeof(*cmd));
4533     memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4534     memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4535     memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
4536 
4537     return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4538                          NO_SYNC_WMIFLAG));
4539 }
4540 
4541 int
4542 wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
4543 {
4544     void *osbuf;
4545     WMI_BEACON_INT_CMD *cmd;
4546 
4547     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4548     if (osbuf == NULL) {
4549         return A_NO_MEMORY;
4550     }
4551 
4552     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4553 
4554     cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
4555     A_MEMZERO(cmd, sizeof(*cmd));
4556     cmd->beaconInterval = intvl;
4557 
4558     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
4559             NO_SYNC_WMIFLAG));
4560 }
4561 
4562 
4563 int
4564 wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
4565 {
4566     void *osbuf;
4567     WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
4568 
4569     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4570     if (osbuf == NULL) {
4571         return A_NO_MEMORY;
4572     }
4573 
4574     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4575 
4576     cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
4577     A_MEMZERO(cmd, sizeof(*cmd));
4578     cmd->voicePktSize = voicePktSize;
4579 
4580     return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
4581             NO_SYNC_WMIFLAG));
4582 }
4583 
4584 
4585 int
4586 wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
4587 {
4588     void *osbuf;
4589     WMI_SET_MAX_SP_LEN_CMD *cmd;
4590 
4591     /* maxSPLen is a two-bit value. If user trys to set anything
4592      * other than this, then its invalid
4593      */
4594     if(maxSPLen & ~0x03)
4595         return  A_EINVAL;
4596 
4597     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4598     if (osbuf == NULL) {
4599         return A_NO_MEMORY;
4600     }
4601 
4602     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4603 
4604     cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
4605     A_MEMZERO(cmd, sizeof(*cmd));
4606     cmd->maxSPLen = maxSPLen;
4607 
4608     return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
4609             NO_SYNC_WMIFLAG));
4610 }
4611 
4612 u8 wmi_determine_userPriority(
4613     u8 *pkt,
4614     u32 layer2Pri)
4615 {
4616     u8 ipPri;
4617     iphdr *ipHdr = (iphdr *)pkt;
4618 
4619     /* Determine IPTOS priority */
4620     /*
4621      * IP Tos format :
4622      *      (Refer Pg 57 WMM-test-plan-v1.2)
4623      * IP-TOS - 8bits
4624      *          : DSCP(6-bits) ECN(2-bits)
4625      *          : DSCP - P2 P1 P0 X X X
4626      *              where (P2 P1 P0) form 802.1D
4627      */
4628     ipPri = ipHdr->ip_tos >> 5;
4629     ipPri &= 0x7;
4630 
4631     if ((layer2Pri & 0x7) > ipPri)
4632         return ((u8)layer2Pri & 0x7);
4633     else
4634         return ipPri;
4635 }
4636 
4637 u8 convert_userPriority_to_trafficClass(u8 userPriority)
4638 {
4639     return  (up_to_ac[userPriority & 0x7]);
4640 }
4641 
4642 u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
4643 {
4644     return wmip->wmi_powerMode;
4645 }
4646 
4647 int
4648 wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
4649 {
4650     int ret = 0;
4651 
4652 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
4653 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF  0
4654 #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF      0
4655 #define TSPEC_DELAY_BOUND_ATHEROS_DEF         0
4656 #define TSPEC_MEDIUM_TIME_ATHEROS_DEF         0
4657 #define TSPEC_SBA_ATHEROS_DEF                 0x2000  /* factor is 1 */
4658 
4659     /* Verify TSPEC params for ATHEROS compliance */
4660     if(tspecCompliance == ATHEROS_COMPLIANCE) {
4661         if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
4662             (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
4663             (pCmd->minDataRate != pCmd->meanDataRate) ||
4664             (pCmd->minDataRate != pCmd->peakDataRate) ||
4665             (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
4666             (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
4667             (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
4668             (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
4669 
4670             A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
4671             //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
4672             ret = A_EINVAL;
4673         }
4674     }
4675 
4676     return ret;
4677 }
4678 
4679 #ifdef CONFIG_HOST_TCMD_SUPPORT
4680 static int
4681 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
4682 {
4683 
4684    A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4685 
4686    A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
4687 
4688    return 0;
4689 }
4690 
4691 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
4692 
4693 int
4694 wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
4695 {
4696     void *osbuf;
4697     WMI_SET_AUTH_MODE_CMD *cmd;
4698 
4699     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4700     if (osbuf == NULL) {
4701         return A_NO_MEMORY;
4702     }
4703 
4704     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4705 
4706     cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4707     A_MEMZERO(cmd, sizeof(*cmd));
4708     cmd->mode = mode;
4709 
4710     return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
4711             NO_SYNC_WMIFLAG));
4712 }
4713 
4714 int
4715 wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
4716 {
4717     void *osbuf;
4718     WMI_SET_REASSOC_MODE_CMD *cmd;
4719 
4720     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4721     if (osbuf == NULL) {
4722         return A_NO_MEMORY;
4723     }
4724 
4725     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4726 
4727     cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4728     A_MEMZERO(cmd, sizeof(*cmd));
4729     cmd->mode = mode;
4730 
4731     return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
4732             NO_SYNC_WMIFLAG));
4733 }
4734 
4735 int
4736 wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
4737 {
4738     void *osbuf;
4739     WMI_SET_LPREAMBLE_CMD *cmd;
4740 
4741     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4742     if (osbuf == NULL) {
4743         return A_NO_MEMORY;
4744     }
4745 
4746     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4747 
4748     cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
4749     A_MEMZERO(cmd, sizeof(*cmd));
4750     cmd->status = status;
4751     cmd->preamblePolicy = preamblePolicy;
4752 
4753     return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
4754             NO_SYNC_WMIFLAG));
4755 }
4756 
4757 int
4758 wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
4759 {
4760     void *osbuf;
4761     WMI_SET_RTS_CMD *cmd;
4762 
4763     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4764     if (osbuf == NULL) {
4765         return A_NO_MEMORY;
4766     }
4767 
4768     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4769 
4770     cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
4771     A_MEMZERO(cmd, sizeof(*cmd));
4772     cmd->threshold = threshold;
4773 
4774     return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
4775             NO_SYNC_WMIFLAG));
4776 }
4777 
4778 int
4779 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
4780 {
4781     void *osbuf;
4782     WMI_SET_WMM_CMD *cmd;
4783 
4784     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4785     if (osbuf == NULL) {
4786         return A_NO_MEMORY;
4787     }
4788 
4789     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4790 
4791     cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
4792     A_MEMZERO(cmd, sizeof(*cmd));
4793     cmd->status = status;
4794 
4795     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
4796             NO_SYNC_WMIFLAG));
4797 
4798 }
4799 
4800 int
4801 wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
4802 {
4803     void *osbuf;
4804     WMI_SET_QOS_SUPP_CMD *cmd;
4805 
4806     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4807     if (osbuf == NULL) {
4808         return A_NO_MEMORY;
4809     }
4810 
4811     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4812 
4813     cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
4814     A_MEMZERO(cmd, sizeof(*cmd));
4815     cmd->status = status;
4816     return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
4817             NO_SYNC_WMIFLAG));
4818 }
4819 
4820 
4821 int
4822 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
4823 {
4824     void *osbuf;
4825     WMI_SET_WMM_TXOP_CMD *cmd;
4826 
4827     if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
4828         return A_EINVAL;
4829 
4830     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4831     if (osbuf == NULL) {
4832         return A_NO_MEMORY;
4833     }
4834 
4835     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4836 
4837     cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
4838     A_MEMZERO(cmd, sizeof(*cmd));
4839     cmd->txopEnable = cfg;
4840 
4841     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
4842             NO_SYNC_WMIFLAG));
4843 
4844 }
4845 
4846 int
4847 wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
4848 {
4849     void *osbuf;
4850     WMI_AP_SET_COUNTRY_CMD *cmd;
4851 
4852     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4853     if (osbuf == NULL) {
4854         return A_NO_MEMORY;
4855     }
4856 
4857     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4858 
4859     cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
4860     A_MEMZERO(cmd, sizeof(*cmd));
4861     memcpy(cmd->countryCode,countryCode,3);
4862 
4863     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
4864             NO_SYNC_WMIFLAG));
4865 }
4866 
4867 #ifdef CONFIG_HOST_TCMD_SUPPORT
4868 /* WMI  layer doesn't need to know the data type of the test cmd.
4869    This would be beneficial for customers like Qualcomm, who might
4870    have different test command requirements from different manufacturers
4871  */
4872 int
4873 wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
4874 {
4875     void *osbuf;
4876     char *data;
4877 
4878     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4879 
4880     osbuf= A_NETBUF_ALLOC(len);
4881     if(osbuf == NULL)
4882     {
4883         return A_NO_MEMORY;
4884     }
4885     A_NETBUF_PUT(osbuf, len);
4886     data = A_NETBUF_DATA(osbuf);
4887     memcpy(data, buf, len);
4888 
4889     return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4890          NO_SYNC_WMIFLAG));
4891 }
4892 
4893 #endif
4894 
4895 int
4896 wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
4897 {
4898     void *osbuf;
4899     WMI_SET_BT_STATUS_CMD *cmd;
4900 
4901     AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
4902 
4903     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4904     if (osbuf == NULL) {
4905         return A_NO_MEMORY;
4906     }
4907 
4908     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4909 
4910     cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4911     A_MEMZERO(cmd, sizeof(*cmd));
4912     cmd->streamType = streamType;
4913     cmd->status = status;
4914 
4915     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
4916             NO_SYNC_WMIFLAG));
4917 }
4918 
4919 int
4920 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
4921 {
4922     void *osbuf;
4923     WMI_SET_BT_PARAMS_CMD* alloc_cmd;
4924 
4925     AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
4926 
4927     if (cmd->paramType == BT_PARAM_SCO) {
4928       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,
4929         cmd->info.scoParams.dataResponseTimeout,
4930         cmd->info.scoParams.stompScoRules,
4931         cmd->info.scoParams.scoOptFlags,
4932         cmd->info.scoParams.stompDutyCyleVal,
4933         cmd->info.scoParams.stompDutyCyleMaxVal,
4934         cmd->info.scoParams.psPollLatencyFraction,
4935         cmd->info.scoParams.noSCOSlots,
4936         cmd->info.scoParams.noIdleSlots,
4937         cmd->info.scoParams.scoOptOffRssi,
4938         cmd->info.scoParams.scoOptOnRssi,
4939         cmd->info.scoParams.scoOptRtsCount));
4940     }
4941     else if (cmd->paramType == BT_PARAM_A2DP) {
4942       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
4943         cmd->info.a2dpParams.a2dpBurstCntMin,
4944         cmd->info.a2dpParams.a2dpDataRespTimeout,
4945         cmd->info.a2dpParams.a2dpOptFlags,
4946         cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
4947         cmd->info.a2dpParams.a2dpOptOffRssi,
4948         cmd->info.a2dpParams.a2dpOptOnRssi,
4949         cmd->info.a2dpParams.a2dpOptRtsCount));
4950     }
4951     else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
4952       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
4953     }
4954     else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
4955       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
4956     }
4957     else if (cmd->paramType == BT_PARAM_ACLCOEX) {
4958       AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
4959         cmd->info.aclCoexParams.aclBtMediumUsageTime,
4960         cmd->info.aclCoexParams.aclDataRespTimeout));
4961     }
4962     else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
4963       A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
4964     }
4965 
4966     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4967     if (osbuf == NULL) {
4968         return A_NO_MEMORY;
4969     }
4970 
4971     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4972 
4973     alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4974     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4975     memcpy(alloc_cmd, cmd, sizeof(*cmd));
4976 
4977     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4978             NO_SYNC_WMIFLAG));
4979 }
4980 
4981 int
4982 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
4983 {
4984 	void *osbuf;
4985     WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
4986 
4987     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4988     if (osbuf == NULL) {
4989         return A_NO_MEMORY;
4990     }
4991     A_NETBUF_PUT(osbuf, sizeof(*cmd));
4992     alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
4993     A_MEMZERO(alloc_cmd, sizeof(*cmd));
4994 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
4995     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4996                          NO_SYNC_WMIFLAG));
4997 
4998 }
4999 
5000 
5001 int
5002 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
5003 						WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
5004 {
5005 	void *osbuf;
5006     WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
5007 
5008     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5009     if (osbuf == NULL) {
5010         return A_NO_MEMORY;
5011     }
5012     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5013     alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
5014     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5015     memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
5016     A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
5017     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
5018                          NO_SYNC_WMIFLAG));
5019 
5020 }
5021 
5022 int
5023 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
5024 						WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
5025 {
5026 	void *osbuf;
5027     WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
5028 
5029     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5030     if (osbuf == NULL) {
5031         return A_NO_MEMORY;
5032     }
5033     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5034     alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
5035     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5036 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
5037     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
5038                          NO_SYNC_WMIFLAG));
5039 
5040 }
5041 
5042 int
5043 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
5044 						WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
5045 {
5046 	void *osbuf;
5047     WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
5048 
5049     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5050     if (osbuf == NULL) {
5051         return A_NO_MEMORY;
5052     }
5053     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5054     alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
5055     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5056 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
5057     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
5058                          NO_SYNC_WMIFLAG));
5059 
5060 }
5061 
5062 int
5063 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
5064 						WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
5065 {
5066 	void *osbuf;
5067     WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
5068 
5069     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5070     if (osbuf == NULL) {
5071         return A_NO_MEMORY;
5072     }
5073     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5074     alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
5075     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5076 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
5077     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
5078                          NO_SYNC_WMIFLAG));
5079 
5080 }
5081 
5082 int
5083 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
5084 						WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
5085 {
5086 	void *osbuf;
5087     WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
5088 
5089     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5090     if (osbuf == NULL) {
5091         return A_NO_MEMORY;
5092     }
5093     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5094     alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
5095     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5096 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
5097     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
5098                          NO_SYNC_WMIFLAG));
5099 
5100 }
5101 
5102 int
5103 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
5104 {
5105 	void *osbuf;
5106 	WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
5107 
5108 	osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5109 	if (osbuf == NULL) {
5110 			return A_NO_MEMORY;
5111 	}
5112 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
5113 	alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
5114 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
5115 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
5116 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
5117 							 NO_SYNC_WMIFLAG));
5118 
5119 }
5120 
5121 int
5122 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
5123 					WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
5124 {
5125 	void *osbuf;
5126 	WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
5127 
5128 	osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5129 	if (osbuf == NULL) {
5130 			return A_NO_MEMORY;
5131 	}
5132 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
5133 	alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
5134 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
5135 	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
5136 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
5137 								 NO_SYNC_WMIFLAG));
5138 
5139 }
5140 
5141 int
5142 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
5143 {
5144 	void *osbuf;
5145 	WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
5146 
5147 	osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5148 	if (osbuf == NULL) {
5149 			return A_NO_MEMORY;
5150 	}
5151 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
5152 	alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
5153 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
5154 	memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
5155 	return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
5156 							 NO_SYNC_WMIFLAG));
5157 
5158 }
5159 
5160 int
5161 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
5162 {
5163 
5164     return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
5165 
5166 }
5167 
5168 int
5169 wmi_get_keepalive_configured(struct wmi_t *wmip)
5170 {
5171     void *osbuf;
5172     WMI_GET_KEEPALIVE_CMD *cmd;
5173     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5174     if (osbuf == NULL) {
5175         return A_NO_MEMORY;
5176     }
5177     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5178     cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
5179     A_MEMZERO(cmd, sizeof(*cmd));
5180     return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
5181                          NO_SYNC_WMIFLAG));
5182 }
5183 
5184 u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
5185 {
5186     return wmip->wmi_keepaliveInterval;
5187 }
5188 
5189 int
5190 wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
5191 {
5192     void *osbuf;
5193     WMI_SET_KEEPALIVE_CMD *cmd;
5194 
5195     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5196     if (osbuf == NULL) {
5197         return A_NO_MEMORY;
5198     }
5199 
5200     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5201 
5202     cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
5203     A_MEMZERO(cmd, sizeof(*cmd));
5204     cmd->keepaliveInterval = keepaliveInterval;
5205     wmip->wmi_keepaliveInterval = keepaliveInterval;
5206 
5207     return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
5208                          NO_SYNC_WMIFLAG));
5209 }
5210 
5211 int
5212 wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
5213 {
5214     void *osbuf;
5215     WMI_SET_PARAMS_CMD *cmd;
5216 
5217     osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
5218     if (osbuf == NULL) {
5219         return A_NO_MEMORY;
5220     }
5221 
5222     A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
5223 
5224     cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5225     A_MEMZERO(cmd, sizeof(*cmd));
5226     cmd->opcode = opcode;
5227     cmd->length = length;
5228     memcpy(cmd->buffer, buffer, length);
5229 
5230     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5231                          NO_SYNC_WMIFLAG));
5232 }
5233 
5234 
5235 int
5236 wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5237 {
5238     void *osbuf;
5239     WMI_SET_MCAST_FILTER_CMD *cmd;
5240 
5241     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5242     if (osbuf == NULL) {
5243         return A_NO_MEMORY;
5244     }
5245 
5246     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5247 
5248     cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5249     cmd->multicast_mac[0] = 0x01;
5250     cmd->multicast_mac[1] = 0x00;
5251     cmd->multicast_mac[2] = 0x5e;
5252     cmd->multicast_mac[3] = dot2&0x7F;
5253     cmd->multicast_mac[4] = dot3;
5254     cmd->multicast_mac[5] = dot4;
5255 
5256     return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
5257                          NO_SYNC_WMIFLAG));
5258 }
5259 
5260 
5261 int
5262 wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5263 {
5264     void *osbuf;
5265     WMI_SET_MCAST_FILTER_CMD *cmd;
5266 
5267     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5268     if (osbuf == NULL) {
5269         return A_NO_MEMORY;
5270     }
5271 
5272     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5273 
5274     cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5275     cmd->multicast_mac[0] = 0x01;
5276     cmd->multicast_mac[1] = 0x00;
5277     cmd->multicast_mac[2] = 0x5e;
5278     cmd->multicast_mac[3] = dot2&0x7F;
5279     cmd->multicast_mac[4] = dot3;
5280     cmd->multicast_mac[5] = dot4;
5281 
5282     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID,
5283                          NO_SYNC_WMIFLAG));
5284 }
5285 
5286 int
5287 wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
5288 {
5289     void *osbuf;
5290     WMI_MCAST_FILTER_CMD *cmd;
5291 
5292     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5293     if (osbuf == NULL) {
5294         return A_NO_MEMORY;
5295     }
5296 
5297     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5298 
5299     cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5300     cmd->enable = enable;
5301 
5302     return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
5303                          NO_SYNC_WMIFLAG));
5304 }
5305 
5306 int
5307 wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5308                   u8 *ieInfo)
5309 {
5310     void *osbuf;
5311     WMI_SET_APPIE_CMD *cmd;
5312     u16 cmdLen;
5313 
5314     cmdLen = sizeof(*cmd) + ieLen - 1;
5315     osbuf = A_NETBUF_ALLOC(cmdLen);
5316     if (osbuf == NULL) {
5317         return A_NO_MEMORY;
5318     }
5319 
5320     A_NETBUF_PUT(osbuf, cmdLen);
5321 
5322     cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
5323     A_MEMZERO(cmd, cmdLen);
5324 
5325     cmd->mgmtFrmType = mgmtFrmType;
5326     cmd->ieLen = ieLen;
5327     memcpy(cmd->ieInfo, ieInfo, ieLen);
5328 
5329     return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5330 }
5331 
5332 int
5333 wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
5334 {
5335     void *osbuf;
5336     u8 *data;
5337 
5338     osbuf = A_NETBUF_ALLOC(dataLen);
5339     if (osbuf == NULL) {
5340         return A_NO_MEMORY;
5341     }
5342 
5343     A_NETBUF_PUT(osbuf, dataLen);
5344 
5345     data = A_NETBUF_DATA(osbuf);
5346 
5347     memcpy(data, cmd, dataLen);
5348 
5349     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5350 }
5351 
5352 s32 wmi_get_rate(s8 rateindex)
5353 {
5354     if (rateindex == RATE_AUTO) {
5355         return 0;
5356     } else {
5357         return(wmi_rateTable[(u32) rateindex][0]);
5358     }
5359 }
5360 
5361 void
5362 wmi_node_return (struct wmi_t *wmip, bss_t *bss)
5363 {
5364     if (NULL != bss)
5365     {
5366         wlan_node_return (&wmip->wmi_scan_table, bss);
5367     }
5368 }
5369 
5370 void
5371 wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
5372 {
5373     wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5374 }
5375 
5376 bss_t *
5377 wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
5378                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
5379 {
5380     bss_t *node = NULL;
5381     node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
5382                                ssidLength, bIsWPA2, bMatchSSID);
5383     return node;
5384 }
5385 
5386 
5387 #ifdef THREAD_X
5388 void
5389 wmi_refresh_scan_table (struct wmi_t *wmip)
5390 {
5391 	wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5392 }
5393 #endif
5394 
5395 void
5396 wmi_free_allnodes(struct wmi_t *wmip)
5397 {
5398     wlan_free_allnodes(&wmip->wmi_scan_table);
5399 }
5400 
5401 bss_t *
5402 wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
5403 {
5404     bss_t *ni=NULL;
5405     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5406     return ni;
5407 }
5408 
5409 void
5410 wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
5411 {
5412     bss_t *ni=NULL;
5413 
5414     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5415     if (ni != NULL) {
5416         wlan_node_reclaim(&wmip->wmi_scan_table, ni);
5417     }
5418 
5419     return;
5420 }
5421 
5422 int
5423 wmi_dset_open_reply(struct wmi_t *wmip,
5424                     u32 status,
5425                     u32 access_cookie,
5426                     u32 dset_size,
5427                     u32 dset_version,
5428                     u32 targ_handle,
5429                     u32 targ_reply_fn,
5430                     u32 targ_reply_arg)
5431 {
5432     void *osbuf;
5433     WMIX_DSETOPEN_REPLY_CMD *open_reply;
5434 
5435     A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
5436 
5437     osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
5438     if (osbuf == NULL) {
5439         return A_NO_MEMORY;
5440     }
5441 
5442     A_NETBUF_PUT(osbuf, sizeof(*open_reply));
5443     open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5444 
5445     open_reply->status                   = status;
5446     open_reply->targ_dset_handle         = targ_handle;
5447     open_reply->targ_reply_fn            = targ_reply_fn;
5448     open_reply->targ_reply_arg           = targ_reply_arg;
5449     open_reply->access_cookie            = access_cookie;
5450     open_reply->size                     = dset_size;
5451     open_reply->version                  = dset_version;
5452 
5453     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
5454                              NO_SYNC_WMIFLAG));
5455 }
5456 
5457 static int
5458 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5459 {
5460     WMI_PMKID_LIST_REPLY *reply;
5461     u32 expected_len;
5462 
5463     if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
5464         return A_EINVAL;
5465     }
5466     reply = (WMI_PMKID_LIST_REPLY *)datap;
5467     expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
5468 
5469     if (len < expected_len) {
5470         return A_EINVAL;
5471     }
5472 
5473     A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
5474                            reply->pmkidList, reply->bssidList[0]);
5475 
5476     return 0;
5477 }
5478 
5479 
5480 static int
5481 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5482 {
5483     WMI_SET_PARAMS_REPLY *reply;
5484 
5485     if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
5486         return A_EINVAL;
5487     }
5488     reply = (WMI_SET_PARAMS_REPLY *)datap;
5489 
5490     if (0 == reply->status)
5491     {
5492 
5493     }
5494     else
5495     {
5496 
5497     }
5498 
5499     return 0;
5500 }
5501 
5502 
5503 
5504 static int
5505 wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5506 {
5507     WMI_ACM_REJECT_EVENT *ev;
5508 
5509     ev = (WMI_ACM_REJECT_EVENT *)datap;
5510     wmip->wmi_traffic_class = ev->trafficClass;
5511     printk("ACM REJECT %d\n",wmip->wmi_traffic_class);
5512     return 0;
5513 }
5514 
5515 
5516 #ifdef CONFIG_HOST_DSET_SUPPORT
5517 int
5518 wmi_dset_data_reply(struct wmi_t *wmip,
5519                     u32 status,
5520                     u8 *user_buf,
5521                     u32 length,
5522                     u32 targ_buf,
5523                     u32 targ_reply_fn,
5524                     u32 targ_reply_arg)
5525 {
5526     void *osbuf;
5527     WMIX_DSETDATA_REPLY_CMD *data_reply;
5528     u32 size;
5529 
5530     size = sizeof(*data_reply) + length;
5531 
5532     if (size <= length) {
5533         return A_ERROR;
5534     }
5535 
5536     A_DPRINTF(DBG_WMI,
5537         (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
5538 
5539     osbuf = A_NETBUF_ALLOC(size);
5540     if (osbuf == NULL) {
5541         return A_NO_MEMORY;
5542     }
5543     A_NETBUF_PUT(osbuf, size);
5544     data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5545 
5546     data_reply->status                     = status;
5547     data_reply->targ_buf                   = targ_buf;
5548     data_reply->targ_reply_fn              = targ_reply_fn;
5549     data_reply->targ_reply_arg             = targ_reply_arg;
5550     data_reply->length                     = length;
5551 
5552     if (status == 0) {
5553         if (a_copy_from_user(data_reply->buf, user_buf, length)) {
5554             A_NETBUF_FREE(osbuf);
5555             return A_ERROR;
5556         }
5557     }
5558 
5559     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
5560                              NO_SYNC_WMIFLAG));
5561 }
5562 #endif /* CONFIG_HOST_DSET_SUPPORT */
5563 
5564 int
5565 wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
5566 {
5567     void *osbuf;
5568     char *cmd;
5569 
5570     wps_enable = status;
5571 
5572     osbuf = a_netbuf_alloc(sizeof(1));
5573     if (osbuf == NULL) {
5574         return A_NO_MEMORY;
5575     }
5576 
5577     a_netbuf_put(osbuf, sizeof(1));
5578 
5579     cmd = (char *)(a_netbuf_to_data(osbuf));
5580 
5581     A_MEMZERO(cmd, sizeof(*cmd));
5582     cmd[0] = (status?1:0);
5583     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
5584                          NO_SYNC_WMIFLAG));
5585 }
5586 
5587 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
5588 int
5589 wmi_prof_cfg_cmd(struct wmi_t *wmip,
5590                  u32 period,
5591                  u32 nbins)
5592 {
5593     void *osbuf;
5594     WMIX_PROF_CFG_CMD *cmd;
5595 
5596     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5597     if (osbuf == NULL) {
5598         return A_NO_MEMORY;
5599     }
5600 
5601     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5602 
5603     cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
5604     A_MEMZERO(cmd, sizeof(*cmd));
5605     cmd->period = period;
5606     cmd->nbins  = nbins;
5607 
5608     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
5609 }
5610 
5611 int
5612 wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
5613 {
5614     void *osbuf;
5615     WMIX_PROF_ADDR_SET_CMD *cmd;
5616 
5617     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5618     if (osbuf == NULL) {
5619         return A_NO_MEMORY;
5620     }
5621 
5622     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5623 
5624     cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
5625     A_MEMZERO(cmd, sizeof(*cmd));
5626     cmd->addr = addr;
5627 
5628     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
5629 }
5630 
5631 int
5632 wmi_prof_start_cmd(struct wmi_t *wmip)
5633 {
5634     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5635 }
5636 
5637 int
5638 wmi_prof_stop_cmd(struct wmi_t *wmip)
5639 {
5640     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5641 }
5642 
5643 int
5644 wmi_prof_count_get_cmd(struct wmi_t *wmip)
5645 {
5646     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
5647 }
5648 
5649 /* Called to handle WMIX_PROF_CONT_EVENTID */
5650 static int
5651 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
5652 {
5653     WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
5654 
5655     A_DPRINTF(DBG_WMI,
5656         (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
5657         prof_data->addr, prof_data->count));
5658 
5659     A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
5660 
5661     return 0;
5662 }
5663 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5664 
5665 #ifdef OS_ROAM_MANAGEMENT
5666 
5667 #define ETHERNET_MAC_ADDRESS_LENGTH    6
5668 
5669 void
5670 wmi_scan_indication (struct wmi_t *wmip)
5671 {
5672     struct ieee80211_node_table *nt;
5673     u32 gen;
5674     u32 size;
5675     u32 bsssize;
5676     bss_t *bss;
5677     u32 numbss;
5678     PNDIS_802_11_BSSID_SCAN_INFO psi;
5679     PBYTE  pie;
5680     NDIS_802_11_FIXED_IEs *pFixed;
5681     NDIS_802_11_VARIABLE_IEs *pVar;
5682     u32 RateSize;
5683 
5684     struct ar6kScanIndication
5685     {
5686         NDIS_802_11_STATUS_INDICATION     ind;
5687         NDIS_802_11_BSSID_SCAN_INFO_LIST  slist;
5688     } *pAr6kScanIndEvent;
5689 
5690     nt = &wmip->wmi_scan_table;
5691 
5692     ++nt->nt_si_gen;
5693 
5694 
5695     gen = nt->nt_si_gen;
5696 
5697     size = offsetof(struct ar6kScanIndication, slist) +
5698            offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
5699 
5700     numbss = 0;
5701 
5702     IEEE80211_NODE_LOCK(nt);
5703 
5704     //calc size
5705     for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5706         if (bss->ni_si_gen != gen) {
5707             bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
5708             bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5709 
5710 #ifdef SUPPORT_WPA2
5711             if (bss->ni_cie.ie_rsn) {
5712                 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5713             }
5714 #endif
5715             if (bss->ni_cie.ie_wpa) {
5716                 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5717             }
5718 
5719             // bsssize must be a multiple of 4 to maintain alignment.
5720             bsssize = (bsssize + 3) & ~3;
5721 
5722             size += bsssize;
5723 
5724             numbss++;
5725         }
5726     }
5727 
5728     if (0 == numbss)
5729     {
5730 //        RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
5731         ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
5732         IEEE80211_NODE_UNLOCK (nt);
5733         return;
5734     }
5735 
5736     pAr6kScanIndEvent = A_MALLOC(size);
5737 
5738     if (NULL == pAr6kScanIndEvent)
5739     {
5740         IEEE80211_NODE_UNLOCK(nt);
5741         return;
5742     }
5743 
5744     A_MEMZERO(pAr6kScanIndEvent, size);
5745 
5746     //copy data
5747     pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
5748     pAr6kScanIndEvent->slist.Version = 1;
5749     pAr6kScanIndEvent->slist.NumItems = numbss;
5750 
5751     psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
5752 
5753     for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5754         if (bss->ni_si_gen != gen) {
5755 
5756             bss->ni_si_gen = gen;
5757 
5758             //Set scan time
5759             psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
5760 
5761             // Copy data to bssid_ex
5762             bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
5763             bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5764 
5765 #ifdef SUPPORT_WPA2
5766             if (bss->ni_cie.ie_rsn) {
5767                 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5768             }
5769 #endif
5770             if (bss->ni_cie.ie_wpa) {
5771                 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5772             }
5773 
5774             // bsssize must be a multiple of 4 to maintain alignment.
5775             bsssize = (bsssize + 3) & ~3;
5776 
5777             psi->Bssid.Length = bsssize;
5778 
5779             memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
5780 
5781 
5782 //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
5783 //  ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
5784 //            RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
5785 
5786             psi->Bssid.Ssid.SsidLength = 0;
5787             pie = bss->ni_cie.ie_ssid;
5788 
5789             if (pie) {
5790                 // Format of SSID IE is:
5791                 //  Type   (1 octet)
5792                 //  Length (1 octet)
5793                 //  SSID (Length octets)
5794                 //
5795                 //  Validation of the IE should have occurred within WMI.
5796                 //
5797                 if (pie[1] <= 32) {
5798                     psi->Bssid.Ssid.SsidLength = pie[1];
5799                     memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
5800                 }
5801             }
5802             psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
5803 
5804             //Post the RSSI value relative to the Standard Noise floor value.
5805             psi->Bssid.Rssi = bss->ni_rssi;
5806 
5807             if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
5808 
5809                 if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
5810                     psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
5811                 }
5812                 else {
5813                     psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
5814                 }
5815             }
5816             else {
5817                 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
5818             }
5819 
5820             psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
5821             psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
5822             psi->Bssid.Configuration.ATIMWindow =  0;
5823             psi->Bssid.Configuration.DSConfig =  bss->ni_cie.ie_chan * 1000;
5824             psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
5825 
5826             RateSize = 0;
5827             pie = bss->ni_cie.ie_rates;
5828             if (pie) {
5829                 RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
5830                 memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
5831             }
5832             pie = bss->ni_cie.ie_xrates;
5833             if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
5834                 memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
5835                        (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
5836             }
5837 
5838             // Copy the fixed IEs
5839             psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
5840 
5841             pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
5842             memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
5843             pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
5844             pFixed->Capabilities = bss->ni_cie.ie_capInfo;
5845 
5846             // Copy selected variable IEs
5847 
5848             pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
5849 
5850 #ifdef SUPPORT_WPA2
5851             // Copy the WPAv2 IE
5852             if (bss->ni_cie.ie_rsn) {
5853                 pie = bss->ni_cie.ie_rsn;
5854                 psi->Bssid.IELength += pie[1] + 2;
5855                 memcpy(pVar, pie, pie[1] + 2);
5856                 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5857             }
5858 #endif
5859             // Copy the WPAv1 IE
5860             if (bss->ni_cie.ie_wpa) {
5861                 pie = bss->ni_cie.ie_wpa;
5862                 psi->Bssid.IELength += pie[1] + 2;
5863                 memcpy(pVar, pie, pie[1] + 2);
5864                 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5865             }
5866 
5867             // Advance buffer pointer
5868             psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
5869         }
5870     }
5871 
5872     IEEE80211_NODE_UNLOCK(nt);
5873 
5874 //    wmi_free_allnodes(wmip);
5875 
5876 //    RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
5877 
5878     ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
5879 
5880     A_FREE(pAr6kScanIndEvent);
5881 }
5882 #endif
5883 
5884 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5885                            u32 size)
5886 {
5887     u32 index;
5888     u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
5889 
5890     /* The list is already in sorted order. Get the next lower value */
5891     for (index = 0; index < size; index ++) {
5892         if (rssi < sq_thresh->upper_threshold[index]) {
5893             threshold = (u8)sq_thresh->upper_threshold[index];
5894             break;
5895         }
5896     }
5897 
5898     return threshold;
5899 }
5900 
5901 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5902                            u32 size)
5903 {
5904     u32 index;
5905     u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
5906 
5907     /* The list is already in sorted order. Get the next lower value */
5908     for (index = 0; index < size; index ++) {
5909         if (rssi > sq_thresh->lower_threshold[index]) {
5910             threshold = (u8)sq_thresh->lower_threshold[index];
5911             break;
5912         }
5913     }
5914 
5915     return threshold;
5916 }
5917 static int
5918 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5919                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5920 {
5921     void    *osbuf;
5922     s8 size;
5923     WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
5924 
5925     size = sizeof (*cmd);
5926 
5927     osbuf = A_NETBUF_ALLOC(size);
5928     if (osbuf == NULL) {
5929         return A_NO_MEMORY;
5930     }
5931 
5932     A_NETBUF_PUT(osbuf, size);
5933 
5934     cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5935     A_MEMZERO(cmd, size);
5936     memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
5937 
5938     return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5939                             NO_SYNC_WMIFLAG));
5940 }
5941 static int
5942 wmi_send_snr_threshold_params(struct wmi_t *wmip,
5943                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5944 {
5945     void    *osbuf;
5946     s8 size;
5947     WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
5948 
5949     size = sizeof (*cmd);
5950 
5951     osbuf = A_NETBUF_ALLOC(size);
5952     if (osbuf == NULL) {
5953         return A_NO_MEMORY;
5954     }
5955 
5956     A_NETBUF_PUT(osbuf, size);
5957     cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5958     A_MEMZERO(cmd, size);
5959     memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
5960 
5961     return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5962                             NO_SYNC_WMIFLAG));
5963 }
5964 
5965 int
5966 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
5967 {
5968     void *osbuf;
5969     WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
5970 
5971     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5972     if (osbuf == NULL) {
5973         return A_NO_MEMORY;
5974     }
5975 
5976     A_NETBUF_PUT(osbuf, sizeof(*cmd));
5977 
5978     alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
5979     A_MEMZERO(alloc_cmd, sizeof(*cmd));
5980     memcpy(alloc_cmd, cmd, sizeof(*cmd));
5981 
5982     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5983             NO_SYNC_WMIFLAG));
5984 }
5985 
5986 bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
5987 {
5988     wmi_get_current_bssid (wmip, id);
5989     return wlan_node_remove (&wmip->wmi_scan_table, id);
5990 }
5991 
5992 int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
5993 {
5994     wlan_setup_node (&wmip->wmi_scan_table, bss, id);
5995     return 0;
5996 }
5997 
5998 #ifdef ATH_AR6K_11N_SUPPORT
5999 static int
6000 wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6001 {
6002     WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
6003 
6004     A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
6005 
6006     return 0;
6007 }
6008 
6009 
6010 static int
6011 wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6012 {
6013     WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
6014 
6015     A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
6016 
6017     return 0;
6018 }
6019 
6020 static int
6021 wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6022 {
6023     WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
6024 
6025     A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
6026 
6027     return 0;
6028 }
6029 
6030 int
6031 wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6032 {
6033 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
6034 
6035     A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
6036 
6037      return 0;
6038 }
6039 
6040 
6041 int
6042 wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
6043 {
6044 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
6045 
6046     A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
6047 
6048      return 0;
6049 
6050 }
6051 #endif
6052 
6053 static int
6054 wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6055 {
6056     WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
6057     A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
6058 
6059     return 0;
6060 }
6061 
6062 ////////////////////////////////////////////////////////////////////////////////
6063 ////                                                                        ////
6064 ////                AP mode functions                                       ////
6065 ////                                                                        ////
6066 ////////////////////////////////////////////////////////////////////////////////
6067 /*
6068  * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
6069  *
6070  * When AR6K in AP mode, This command will be called after
6071  * changing ssid, channel etc. It will pass the profile to
6072  * target with a flag which will indicate which parameter changed,
6073  * also if this flag is 0, there was no change in parametes, so
6074  * commit cmd will not be sent to target. Without calling this IOCTL
6075  * the changes will not take effect.
6076  */
6077 int
6078 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
6079 {
6080     void *osbuf;
6081     WMI_CONNECT_CMD *cm;
6082 
6083     osbuf = A_NETBUF_ALLOC(sizeof(*cm));
6084     if (osbuf == NULL) {
6085         return A_NO_MEMORY;
6086     }
6087 
6088     A_NETBUF_PUT(osbuf, sizeof(*cm));
6089     cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
6090     A_MEMZERO(cm, sizeof(*cm));
6091 
6092     memcpy(cm,p,sizeof(*cm));
6093 
6094     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
6095 }
6096 
6097 /*
6098  * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
6099  *
6100  * This command will be used to enable/disable hidden ssid functioanlity of
6101  * beacon. If it is enabled, ssid will be NULL in beacon.
6102  */
6103 int
6104 wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
6105 {
6106     void *osbuf;
6107     WMI_AP_HIDDEN_SSID_CMD *hs;
6108 
6109     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
6110     if (osbuf == NULL) {
6111         return A_NO_MEMORY;
6112     }
6113 
6114     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
6115     hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
6116     A_MEMZERO(hs, sizeof(*hs));
6117 
6118     hs->hidden_ssid          = hidden_ssid;
6119 
6120     A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
6121     return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
6122 }
6123 
6124 /*
6125  * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
6126  *
6127  * This command is used to limit max num of STA that can connect
6128  * with this AP. This value should not exceed AP_MAX_NUM_STA (this
6129  * is max num of STA supported by AP). Value was already validated
6130  * in ioctl.c
6131  */
6132 int
6133 wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
6134 {
6135     void *osbuf;
6136     WMI_AP_SET_NUM_STA_CMD *ns;
6137 
6138     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
6139     if (osbuf == NULL) {
6140         return A_NO_MEMORY;
6141     }
6142 
6143     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
6144     ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
6145     A_MEMZERO(ns, sizeof(*ns));
6146 
6147     ns->num_sta          = num_sta;
6148 
6149     A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
6150     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
6151 }
6152 
6153 /*
6154  * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
6155  *
6156  * This command is used to send list of mac of STAs which will
6157  * be allowed to connect with this AP. When this list is empty
6158  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
6159  */
6160 int
6161 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
6162 {
6163     void *osbuf;
6164     WMI_AP_ACL_MAC_CMD *a;
6165 
6166     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
6167     if (osbuf == NULL) {
6168         return A_NO_MEMORY;
6169     }
6170 
6171     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
6172     a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
6173     A_MEMZERO(a, sizeof(*a));
6174     memcpy(a,acl,sizeof(*acl));
6175 
6176     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
6177 }
6178 
6179 /*
6180  * IOCTL: AR6000_XIOCTL_AP_SET_MLME
6181  *
6182  * This command is used to send list of mac of STAs which will
6183  * be allowed to connect with this AP. When this list is empty
6184  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
6185  */
6186 int
6187 wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
6188 {
6189     void *osbuf;
6190     WMI_AP_SET_MLME_CMD *mlme;
6191 
6192     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
6193     if (osbuf == NULL) {
6194         return A_NO_MEMORY;
6195     }
6196 
6197     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
6198     mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
6199     A_MEMZERO(mlme, sizeof(*mlme));
6200 
6201     mlme->cmd = cmd;
6202     memcpy(mlme->mac, mac, ATH_MAC_LEN);
6203     mlme->reason = reason;
6204 
6205     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
6206 }
6207 
6208 static int
6209 wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6210 {
6211     WMI_PSPOLL_EVENT *ev;
6212 
6213     if (len < sizeof(WMI_PSPOLL_EVENT)) {
6214         return A_EINVAL;
6215     }
6216     ev = (WMI_PSPOLL_EVENT *)datap;
6217 
6218     A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
6219     return 0;
6220 }
6221 
6222 static int
6223 wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6224 {
6225     A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
6226     return 0;
6227 }
6228 
6229 #ifdef WAPI_ENABLE
6230 static int
6231 wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6232 {
6233     u8 *ev;
6234 
6235     if (len < 7) {
6236         return A_EINVAL;
6237     }
6238     ev = (u8 *)datap;
6239 
6240     A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
6241     return 0;
6242 }
6243 #endif
6244 
6245 int
6246 wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
6247 {
6248     WMI_AP_SET_PVB_CMD *cmd;
6249     void *osbuf = NULL;
6250 
6251     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
6252     if (osbuf == NULL) {
6253         return A_NO_MEMORY;
6254     }
6255 
6256     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
6257     cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
6258     A_MEMZERO(cmd, sizeof(*cmd));
6259 
6260     cmd->aid = aid;
6261     cmd->flag = flag;
6262 
6263     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
6264 }
6265 
6266 int
6267 wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
6268 {
6269     WMI_AP_CONN_INACT_CMD *cmd;
6270     void *osbuf = NULL;
6271 
6272     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
6273     if (osbuf == NULL) {
6274         return A_NO_MEMORY;
6275     }
6276 
6277     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
6278     cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
6279     A_MEMZERO(cmd, sizeof(*cmd));
6280 
6281     cmd->period = period;
6282 
6283     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
6284 }
6285 
6286 int
6287 wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
6288 {
6289     WMI_AP_PROT_SCAN_TIME_CMD *cmd;
6290     void *osbuf = NULL;
6291 
6292     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6293     if (osbuf == NULL) {
6294         return A_NO_MEMORY;
6295     }
6296 
6297     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6298     cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
6299     A_MEMZERO(cmd, sizeof(*cmd));
6300 
6301     cmd->period_min = period;
6302     cmd->dwell_ms   = dwell;
6303 
6304     return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
6305 }
6306 
6307 int
6308 wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
6309 {
6310     WMI_AP_SET_DTIM_CMD *cmd;
6311     void *osbuf = NULL;
6312 
6313     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
6314     if (osbuf == NULL) {
6315         return A_NO_MEMORY;
6316     }
6317 
6318     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
6319     cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
6320     A_MEMZERO(cmd, sizeof(*cmd));
6321 
6322     cmd->dtim = dtim;
6323 
6324     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
6325 }
6326 
6327 /*
6328  * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
6329  *
6330  * This command is used to set ACL policay. While changing policy, if you
6331  * want to retain the existing MAC addresses in the ACL list, policy should be
6332  * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
6333  * If there is no chage in policy, the list will be intact.
6334  */
6335 int
6336 wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
6337 {
6338     void *osbuf;
6339     WMI_AP_ACL_POLICY_CMD *po;
6340 
6341     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
6342     if (osbuf == NULL) {
6343         return A_NO_MEMORY;
6344 }
6345 
6346     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
6347     po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
6348     A_MEMZERO(po, sizeof(*po));
6349 
6350     po->policy = policy;
6351 
6352     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
6353 }
6354 
6355 int
6356 wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
6357 {
6358     void *osbuf;
6359     WMI_AP_SET_11BG_RATESET_CMD *rs;
6360 
6361     osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6362     if (osbuf == NULL) {
6363         return A_NO_MEMORY;
6364     }
6365 
6366     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6367     rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
6368     A_MEMZERO(rs, sizeof(*rs));
6369 
6370     rs->rateset = rateset;
6371 
6372     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
6373 }
6374 
6375 #ifdef ATH_AR6K_11N_SUPPORT
6376 int
6377 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
6378 {
6379     void *osbuf;
6380     WMI_SET_HT_CAP_CMD *htCap;
6381     u8 band;
6382 
6383     osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
6384     if (osbuf == NULL) {
6385         return A_NO_MEMORY;
6386     }
6387 
6388     A_NETBUF_PUT(osbuf, sizeof(*htCap));
6389 
6390     band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
6391     wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
6392 
6393     htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
6394     A_MEMZERO(htCap, sizeof(*htCap));
6395     memcpy(htCap, cmd, sizeof(*htCap));
6396 
6397     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6398                          NO_SYNC_WMIFLAG));
6399 }
6400 
6401 int
6402 wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
6403 {
6404     void *osbuf;
6405     WMI_SET_HT_OP_CMD *htInfo;
6406 
6407     osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
6408     if (osbuf == NULL) {
6409         return A_NO_MEMORY;
6410     }
6411 
6412     A_NETBUF_PUT(osbuf, sizeof(*htInfo));
6413 
6414     htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
6415     A_MEMZERO(htInfo, sizeof(*htInfo));
6416     htInfo->sta_chan_width = sta_chan_width;
6417 
6418     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
6419                          NO_SYNC_WMIFLAG));
6420 }
6421 #endif
6422 
6423 int
6424 wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
6425 {
6426     void *osbuf;
6427     WMI_SET_TX_SELECT_RATES_CMD *pData;
6428 
6429     osbuf = A_NETBUF_ALLOC(sizeof(*pData));
6430     if (osbuf == NULL) {
6431         return A_NO_MEMORY;
6432     }
6433 
6434     A_NETBUF_PUT(osbuf, sizeof(*pData));
6435 
6436     pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
6437     memcpy(pData, pMaskArray, sizeof(*pData));
6438 
6439     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6440                          NO_SYNC_WMIFLAG));
6441 }
6442 
6443 
6444 int
6445 wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
6446 {
6447     void *osbuf;
6448     WMI_HCI_CMD *cmd;
6449 
6450     osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
6451     if (osbuf == NULL) {
6452         return A_NO_MEMORY;
6453     }
6454 
6455     A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
6456     cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
6457 
6458     cmd->cmd_buf_sz = sz;
6459     memcpy(cmd->buf, buf, sz);
6460     return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6461 }
6462 
6463 #ifdef ATH_AR6K_11N_SUPPORT
6464 int
6465 wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
6466 {
6467     void *osbuf;
6468     WMI_ALLOW_AGGR_CMD *cmd;
6469 
6470     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6471     if (osbuf == NULL) {
6472         return A_NO_MEMORY;
6473     }
6474 
6475     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6476 
6477     cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
6478     cmd->tx_allow_aggr = tx_tidmask;
6479     cmd->rx_allow_aggr = rx_tidmask;
6480 
6481     return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
6482 }
6483 
6484 int
6485 wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
6486 {
6487     void *osbuf;
6488     WMI_ADDBA_REQ_CMD *cmd;
6489 
6490     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6491     if (osbuf == NULL) {
6492         return A_NO_MEMORY;
6493     }
6494 
6495     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6496 
6497     cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6498     cmd->tid = tid;
6499 
6500     return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6501 }
6502 
6503 int
6504 wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
6505 {
6506     void *osbuf;
6507     WMI_DELBA_REQ_CMD *cmd;
6508 
6509     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6510     if (osbuf == NULL) {
6511         return A_NO_MEMORY;
6512     }
6513 
6514     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6515 
6516     cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6517     cmd->tid = tid;
6518     cmd->is_sender_initiator = uplink;  /* uplink =1 - uplink direction, 0=downlink direction */
6519 
6520     /* Delete the local aggr state, on host */
6521     return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6522 }
6523 #endif
6524 
6525 int
6526 wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
6527                             bool rxDot11Hdr, bool defragOnHost)
6528 {
6529     void *osbuf;
6530     WMI_RX_FRAME_FORMAT_CMD *cmd;
6531 
6532     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6533     if (osbuf == NULL) {
6534         return A_NO_MEMORY;
6535     }
6536 
6537     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6538 
6539     cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
6540     cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6541     cmd->defragOnHost = (defragOnHost==true)? 1:0;
6542     cmd->metaVersion = rxMetaVersion;  /*  */
6543 
6544     /* Delete the local aggr state, on host */
6545     return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
6546 }
6547 
6548 
6549 int
6550 wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
6551 {
6552     void *osbuf;
6553     WMI_SET_THIN_MODE_CMD *cmd;
6554 
6555     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6556     if (osbuf == NULL) {
6557         return A_NO_MEMORY;
6558     }
6559 
6560     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6561 
6562     cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
6563     cmd->enable = (bThinMode==true)? 1:0;
6564 
6565     /* Delete the local aggr state, on host */
6566     return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
6567 }
6568 
6569 
6570 int
6571 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
6572 {
6573     void *osbuf;
6574     WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
6575 
6576     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6577     if (osbuf == NULL) {
6578         return A_NO_MEMORY;
6579     }
6580 
6581     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6582 
6583     cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
6584     A_MEMZERO(cmd, sizeof(*cmd));
6585     cmd->precedence = precedence;
6586 
6587     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
6588                          NO_SYNC_WMIFLAG));
6589 }
6590 
6591 int
6592 wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
6593 {
6594     void *osbuf;
6595     WMI_SET_PMK_CMD *p;
6596 
6597     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
6598     if (osbuf == NULL) {
6599         return A_NO_MEMORY;
6600     }
6601 
6602     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
6603 
6604     p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
6605     A_MEMZERO(p, sizeof(*p));
6606 
6607     memcpy(p->pmk, pmk, WMI_PMK_LEN);
6608 
6609     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6610 }
6611 
6612 int
6613 wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
6614 {
6615     void *osbuf;
6616     WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
6617 
6618     osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6619     if (osbuf == NULL) {
6620         return A_NO_MEMORY;
6621     }
6622 
6623     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6624 
6625     p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
6626     memset(p, 0, sizeof(*p));
6627 
6628     p->threshold = cmd->threshold;
6629 
6630     return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
6631 }
6632 
6633 int
6634 wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
6635 {
6636     void *osbuf;
6637     WMI_SET_TX_SGI_PARAM_CMD *cmd;
6638 
6639     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6640     if (osbuf == NULL) {
6641         return A_NO_MEMORY ;
6642     }
6643 
6644     A_NETBUF_PUT(osbuf, sizeof(*cmd));
6645 
6646     cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
6647     A_MEMZERO(cmd, sizeof(*cmd));
6648     cmd->sgiMask = sgiMask;
6649     cmd->sgiPERThreshold = sgiPERThreshold;
6650     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
6651                          NO_SYNC_WMIFLAG));
6652 }
6653 
6654 bss_t *
6655 wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
6656                    u32 ssidLength,
6657                    u32 dot11AuthMode, u32 authMode,
6658                    u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
6659 {
6660     bss_t *node = NULL;
6661     node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
6662                                ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
6663 
6664     return node;
6665 }
6666 
6667 u16 wmi_ieee2freq (int chan)
6668 {
6669     u16 freq = 0;
6670     freq = wlan_ieee2freq (chan);
6671     return freq;
6672 
6673 }
6674 
6675 u32 wmi_freq2ieee (u16 freq)
6676 {
6677     u16 chan = 0;
6678     chan = wlan_freq2ieee (freq);
6679     return chan;
6680 }
6681