]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/staging/ath6kl/wmi/wmi.c
Fix common misspellings
[mirror_ubuntu-jammy-kernel.git] / drivers / staging / ath6kl / wmi / wmi.c
CommitLineData
30295c89
VM
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
090f807a 51static struct ath_debug_mask_description wmi_debug_desc[] = {
30295c89
VM
52 { ATH_DEBUG_WMI , "General WMI Tracing"},
53};
54
55ATH_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
ab3655da 73static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 74
ab3655da 75static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 76 int len);
ab3655da 77static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
78 int len);
79
ab3655da 80static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 81 int len);
ab3655da 82static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 83 int len);
ab3655da 84static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 85 int len);
ab3655da 86static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 87 int len);
1f4c34bd 88static int wmi_sync_point(struct wmi_t *wmip);
30295c89 89
ab3655da 90static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
30295c89 91 int len);
ab3655da 92static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
30295c89 93 int len);
ab3655da 94static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
30295c89 95 int len);
ab3655da 96static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 97 int len);
ab3655da
JP
98static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
99static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
100 int len);
101
ab3655da 102static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
103 int len);
104#ifdef CONFIG_HOST_DSET_SUPPORT
ab3655da
JP
105static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
106static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
107 int len);
108#endif /* CONFIG_HOST_DSET_SUPPORT */
109
110
ab3655da 111static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
30295c89 112 int len);
ab3655da
JP
113static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
114static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
115static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
116static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
117static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
118static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
119static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
120static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 121 int len);
ab3655da 122static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 123 int len);
ab3655da 124static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 125 int len);
1f4c34bd 126static int
e1ce2a3a 127wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
30295c89 128
1f4c34bd 129static int
e1ce2a3a 130wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
30295c89 131
1f4c34bd 132static int
e1ce2a3a 133wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
30295c89
VM
134
135#ifdef CONFIG_HOST_GPIO_SUPPORT
ab3655da
JP
136static int wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len);
137static int wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len);
138static int wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89
VM
139#endif /* CONFIG_HOST_GPIO_SUPPORT */
140
141#ifdef CONFIG_HOST_TCMD_SUPPORT
1f4c34bd 142static int
ab3655da 143wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89
VM
144#endif
145
1f4c34bd 146static int
ab3655da 147wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 148
1f4c34bd 149static int
ab3655da 150wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 151
1f4c34bd 152static int
ab3655da 153wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 154
1071a134 155static bool
f68057e6 156wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
30295c89 157
1f4c34bd 158static int
ab3655da 159wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 160
1f4c34bd 161static int
ab3655da 162wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 163
ab3655da 164static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 165
1f4c34bd 166int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
30295c89
VM
167 WMI_SYNC_FLAG syncflag);
168
cb1e3709
JP
169u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
170u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
30295c89
VM
171
172void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
173void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
1f4c34bd 174static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
30295c89 175 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
1f4c34bd 176static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
30295c89
VM
177 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
178#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1f4c34bd 179static int
ab3655da 180wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89
VM
181#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
182
ab3655da 183static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89 184 int len);
ab3655da 185static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
186 int len);
187
ab3655da 188static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
30295c89
VM
189 int len);
190#ifdef ATH_AR6K_11N_SUPPORT
ab3655da
JP
191static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
192static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
193static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
194static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
195static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
30295c89 196#endif
ab3655da 197static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
30295c89
VM
198
199#ifdef WAPI_ENABLE
ab3655da 200static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
30295c89
VM
201 int len);
202#endif
203
204#if defined(UNDER_CE)
205#if defined(NDIS51_MINIPORT)
206unsigned int processDot11Hdr = 0;
207#else
208unsigned int processDot11Hdr = 1;
209#endif
210#else
211extern unsigned int processDot11Hdr;
212#endif
213
214int wps_enable;
f68057e6 215static const s32 wmi_rateTable[][2] = {
30295c89
VM
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
f68057e6
JP
247#define MODE_A_SUPPORT_RATE_START ((s32) 4)
248#define MODE_A_SUPPORT_RATE_STOP ((s32) 11)
30295c89
VM
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
f68057e6
JP
253#define MODE_B_SUPPORT_RATE_START ((s32) 0)
254#define MODE_B_SUPPORT_RATE_STOP ((s32) 3)
30295c89 255
f68057e6
JP
256#define MODE_G_SUPPORT_RATE_START ((s32) 0)
257#define MODE_G_SUPPORT_RATE_STOP ((s32) 11)
30295c89 258
f68057e6
JP
259#define MODE_GHT20_SUPPORT_RATE_START ((s32) 0)
260#define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19)
30295c89
VM
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 */
ab3655da 265const u8 up_to_ac[]= {
30295c89
VM
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 */
279typedef PREPACK struct _iphdr {
ab3655da
JP
280 u8 ip_ver_hdrlen; /* version and hdr length */
281 u8 ip_tos; /* type of service */
4853ac05
JP
282 u16 ip_len; /* total length */
283 u16 ip_id; /* identification */
cb1e3709 284 s16 ip_off; /* fragment offset field */
30295c89
VM
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 */
ab3655da
JP
288 u8 ip_ttl; /* time to live */
289 u8 ip_p; /* protocol */
4853ac05 290 u16 ip_sum; /* checksum */
ab3655da
JP
291 u8 ip_src[4]; /* source and dest address */
292 u8 ip_dst[4];
30295c89
VM
293} POSTPACK iphdr;
294
295#include "athendpack.h"
296
cb1e3709
JP
297static s16 rssi_event_value = 0;
298static s16 snr_event_value = 0;
30295c89 299
1071a134 300bool is_probe_ssid = false;
30295c89
VM
301
302void *
303wmi_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
335void
336wmi_qos_state_init(struct wmi_t *wmip)
337{
ab3655da 338 u8 i;
30295c89
VM
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
359void
360wmi_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
366HTC_ENDPOINT_ID
367wmi_get_control_ep(struct wmi_t * wmip)
368{
369 return(wmip->wmi_endpoint_id);
370}
371
372void
373wmi_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 */
1f4c34bd 394int
30295c89
VM
395wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
396{
ab3655da 397 u8 *datap;
4853ac05 398 u16 typeorlen;
30295c89
VM
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
4853ac05 412 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
30295c89
VM
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));
4f69cef0 419 return (0);
30295c89
VM
420 }
421
422 /*
423 * Save mac fields and length to be inserted later
424 */
05209262
LR
425 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
426 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
30295c89
VM
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 */
4f69cef0 433 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
30295c89
VM
434 return A_NO_MEMORY;
435 }
436 datap = A_NETBUF_DATA(osbuf);
437
05209262 438 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
30295c89
VM
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
4f69cef0 449 return (0);
30295c89
VM
450}
451
ab3655da 452int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
30295c89
VM
453{
454 switch(*pVersion){
455 case 0:
4f69cef0 456 return (0);
30295c89
VM
457 case WMI_META_VERSION_1:
458 {
459 WMI_TX_META_V1 *pV1= NULL;
460 A_ASSERT(osbuf != NULL);
4f69cef0 461 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
30295c89
VM
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;
4f69cef0 476 return (0);
30295c89
VM
477 }
478#ifdef CONFIG_CHECKSUM_OFFLOAD
479 case WMI_META_VERSION_2:
480 {
481 WMI_TX_META_V2 *pV2 ;
482 A_ASSERT(osbuf != NULL);
4f69cef0 483 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
30295c89
VM
484 return A_NO_MEMORY;
485 }
486 pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
05209262 487 memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
4f69cef0 488 return (0);
30295c89
VM
489 }
490#endif
491 default:
4f69cef0 492 return (0);
30295c89
VM
493 }
494}
495
496/* Adds a WMI data header */
1f4c34bd 497int
ab3655da
JP
498wmi_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)
30295c89
VM
500{
501 WMI_DATA_HDR *dtHdr;
ab3655da 502// u8 metaVersion = 0;
1f4c34bd 503 int status;
30295c89
VM
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. */
4f69cef0 509 if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
30295c89
VM
510 return status;
511 }
512
4f69cef0 513 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
30295c89
VM
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
4f69cef0 530 return (0);
30295c89
VM
531}
532
533
e1ce2a3a 534u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
30295c89 535{
ab3655da
JP
536 u8 *datap;
537 u8 trafficClass = WMM_AC_BE;
4853ac05 538 u16 ipType = IP_ETHERTYPE;
30295c89 539 WMI_DATA_HDR *dtHdr;
ab3655da
JP
540 u8 streamExists = 0;
541 u8 userPriority;
e1ce2a3a 542 u32 hdrsize, metasize;
30295c89
VM
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 {
e1ce2a3a 567 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
30295c89
VM
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
ab3655da 583 userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
30295c89
VM
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
1f4c34bd 624int
30295c89
VM
625wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
626{
ab3655da 627 u8 *datap;
4853ac05 628 u16 typeorlen;
30295c89
VM
629 ATH_MAC_HDR macHdr;
630 ATH_LLC_SNAP_HDR *llcHdr;
631 struct ieee80211_frame *wh;
e1ce2a3a 632 u32 hdrsize;
30295c89
VM
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
4853ac05 644 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
30295c89
VM
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 */
05209262
LR
657 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
658 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
30295c89
VM
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 */
4f69cef0 667 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
30295c89
VM
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
681AddDot11Hdr:
682 /* Make room for 802.11 hdr */
683 if (wmip->wmi_is_wmm_enabled)
684 {
e1ce2a3a 685 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
4f69cef0 686 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
30295c89
VM
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 {
e1ce2a3a 695 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
4f69cef0 696 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
30295c89
VM
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
4f69cef0 713 return (0);
30295c89
VM
714}
715
1f4c34bd 716int
30295c89
VM
717wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
718{
ab3655da 719 u8 *datap;
30295c89 720 struct ieee80211_frame *pwh,wh;
ab3655da 721 u8 type,subtype;
30295c89
VM
722 ATH_LLC_SNAP_HDR *llcHdr;
723 ATH_MAC_HDR macHdr;
e1ce2a3a 724 u32 hdrsize;
30295c89
VM
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
05209262 733 memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
30295c89
VM
734
735 /* strip off the 802.11 hdr*/
736 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
e1ce2a3a 737 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
30295c89
VM
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
05209262 775 memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
30295c89 776
4f69cef0 777 return 0;
30295c89
VM
778}
779
780/*
781 * performs 802.3 to DIX encapsulation for received packets.
782 * Assumes the entire 802.3 header is contigous.
783 */
1f4c34bd 784int
30295c89
VM
785wmi_dot3_2_dix(void *osbuf)
786{
ab3655da 787 u8 *datap;
30295c89
VM
788 ATH_MAC_HDR macHdr;
789 ATH_LLC_SNAP_HDR *llcHdr;
790
791 A_ASSERT(osbuf != NULL);
792 datap = A_NETBUF_DATA(osbuf);
793
05209262 794 memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
30295c89
VM
795 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
796 macHdr.typeOrLen = llcHdr->etherType;
797
4f69cef0 798 if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
30295c89
VM
799 return A_NO_MEMORY;
800 }
801
802 datap = A_NETBUF_DATA(osbuf);
803
05209262 804 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
30295c89 805
4f69cef0 806 return (0);
30295c89
VM
807}
808
809/*
810 * Removes a WMI data header
811 */
1f4c34bd 812int
30295c89
VM
813wmi_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
820void
821wmi_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 */
1f4c34bd 829int
30295c89
VM
830wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
831{
832 WMIX_CMD_HDR *cmd;
4853ac05 833 u16 id;
ab3655da 834 u8 *datap;
e1ce2a3a 835 u32 len;
4f69cef0 836 int status = 0;
30295c89
VM
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
4f69cef0 847 if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
30295c89
VM
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 */
e1ce2a3a 904u32 cmdRecvNum;
30295c89 905
1f4c34bd 906int
30295c89
VM
907wmi_control_rx(struct wmi_t *wmip, void *osbuf)
908{
909 WMI_CMD_HDR *cmd;
4853ac05 910 u16 id;
ab3655da 911 u8 *datap;
e1ce2a3a 912 u32 len, i, loggingReq;
4f69cef0 913 int status = 0;
30295c89
VM
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
4f69cef0 926 if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
30295c89
VM
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;
05209262 1002 memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
30295c89
VM
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;
05209262 1014 memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
30295c89
VM
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 */
1f4c34bd 1195static int
30295c89
VM
1196wmi_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)
1f4c34bd 1212static int
30295c89
VM
1213wmi_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
1f4c34bd 1226static int
ab3655da 1227wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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));
1071a134 1235 wmip->wmi_ready = true;
30295c89
VM
1236 A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
1237 ev->sw_version, ev->abi_version);
1238
4f69cef0 1239 return 0;
30295c89
VM
1240}
1241
1242#define LE_READ_4(p) \
e1ce2a3a 1243 ((u32) \
ab3655da
JP
1244 ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
1245 (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
30295c89
VM
1246
1247static int __inline
ab3655da 1248iswmmoui(const u8 *frm)
30295c89
VM
1249{
1250 return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1251}
1252
1253static int __inline
ab3655da 1254iswmmparam(const u8 *frm)
30295c89
VM
1255{
1256 return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1257}
1258
1259
1f4c34bd 1260static int
ab3655da 1261wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1262{
1263 WMI_CONNECT_EVENT *ev;
ab3655da 1264 u8 *pie,*peie;
30295c89
VM
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
05209262 1278 memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
30295c89
VM
1279
1280 /* initialize pointer to start of assoc rsp IEs */
1281 pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
4853ac05
JP
1282 sizeof(u16) + /* capinfo*/
1283 sizeof(u16) + /* status Code */
1284 sizeof(u16) ; /* associd */
30295c89
VM
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 {
1071a134 1298 wmip->wmi_is_wmm_enabled = true;
30295c89
VM
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
4f69cef0 1317 return 0;
30295c89
VM
1318}
1319
1f4c34bd 1320static int
ab3655da 1321wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1332 return 0;
30295c89
VM
1333}
1334
1f4c34bd 1335static int
ab3655da 1336wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1353 return 0;
30295c89
VM
1354}
1355
1f4c34bd 1356static int
ab3655da 1357wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
1071a134 1371 wmip->wmi_is_wmm_enabled = false;
30295c89
VM
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
4f69cef0 1378 return 0;
30295c89
VM
1379}
1380
1f4c34bd 1381static int
ab3655da 1382wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1398 return 0;
30295c89
VM
1399}
1400
1f4c34bd 1401static int
ab3655da 1402wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1414 return 0;
30295c89
VM
1415}
1416
1f4c34bd 1417static int
ab3655da 1418wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1419{
1420 bss_t *bss = NULL;
1421 WMI_BSS_INFO_HDR *bih;
ab3655da 1422 u8 *buf;
e1ce2a3a 1423 u32 nodeCachingAllowed = 1;
d8cb316f
LR
1424 u8 cached_ssid_len = 0;
1425 u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
ab3655da 1426 u8 beacon_ssid_len = 0;
30295c89
VM
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)
4f69cef0 1437 return 0; //no node found in the table, just drop the node with incorrect RSSI
30295c89
VM
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,
4f69cef0 1446 &nodeCachingAllowed) != 0) {
30295c89
VM
1447 wmi_node_return(wmip, bss);
1448 return A_EINVAL;
1449 }
1450
1451 if(!nodeCachingAllowed) {
1452 wmi_node_return(wmip, bss);
4f69cef0 1453 return 0;
30295c89
VM
1454 }
1455
1456 buf = datap + sizeof(WMI_BSS_INFO_HDR);
1457 len -= sizeof(WMI_BSS_INFO_HDR);
1458
fa1ae16c
AS
1459 A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
1460 "bssid \"%pM\"\n", DBGARG, bih->channel,
97d23545 1461 (unsigned char) bih->rssi, bih->bssid));
30295c89
VM
1462
1463 if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
1464 wmi_node_return(wmip, bss);
4f69cef0 1465 return 0;
30295c89
VM
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. */
1071a134 1478 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
30295c89 1479 {
d8cb316f 1480 u8 *ie_ssid;
30295c89
VM
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 */
2a4724a7 1497 if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
30295c89
VM
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. */
1071a134 1513 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
30295c89
VM
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. */
1071a134 1532 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
30295c89
VM
1533 (0 != cached_ssid_len) &&
1534 (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1535 {
ab3655da 1536 u8 *ni_buf = bss->ni_buf;
30295c89
VM
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). */
05209262 1541 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
30295c89
VM
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 */
05209262 1550 memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
30295c89
VM
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 */
05209262 1560 memcpy(ni_buf, buf, buf_len);
30295c89
VM
1561 }
1562 else
05209262 1563 memcpy(bss->ni_buf, buf, len);
30295c89
VM
1564
1565 bss->ni_framelen = len;
4f69cef0 1566 if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
30295c89
VM
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
4f69cef0 1578 return 0;
30295c89
VM
1579}
1580
1f4c34bd 1581static int
ab3655da 1582wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1583{
1584 bss_t *bss;
1585 WMI_OPT_RX_INFO_HDR *bih;
ab3655da 1586 u8 *buf;
30295c89
VM
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);
05209262 1617 memcpy(bss->ni_buf, buf, len);
30295c89
VM
1618 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1619
4f69cef0 1620 return 0;
30295c89
VM
1621}
1622
1623 /* This event indicates inactivity timeout of a fatpipe(pstream)
1624 * at the target
1625 */
1f4c34bd 1626static int
ab3655da 1627wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1653 return 0;
30295c89
VM
1654}
1655
1f4c34bd 1656static int
ab3655da 1657wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1658{
1659 WMI_BIT_RATE_REPLY *reply;
f68057e6 1660 s32 rate;
e1ce2a3a 1661 u32 sgi,index;
30295c89
VM
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
f2ab1275 1674 if (reply->rateIndex == (s8) RATE_AUTO) {
30295c89
VM
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);
4f69cef0 1684 return 0;
30295c89
VM
1685}
1686
1f4c34bd 1687static int
ab3655da 1688wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1701 return 0;
30295c89
VM
1702}
1703
1f4c34bd 1704static int
ab3655da 1705wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1718 return 0;
30295c89
VM
1719}
1720
1f4c34bd 1721static int
ab3655da 1722wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1734 return 0;
30295c89 1735}
1f4c34bd 1736static int
ab3655da 1737wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1749 return 0;
30295c89
VM
1750}
1751
1752
1f4c34bd 1753static int
ab3655da 1754wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1770 return 0;
30295c89
VM
1771}
1772
1773#ifdef CONFIG_HOST_DSET_SUPPORT
1f4c34bd 1774static int
ab3655da 1775wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1787 return 0;
30295c89
VM
1788}
1789
1f4c34bd 1790static int
ab3655da 1791wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1809 return 0;
30295c89
VM
1810}
1811#endif /* CONFIG_HOST_DSET_SUPPORT */
1812
1f4c34bd 1813static int
ab3655da 1814wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1815{
1816 WMI_SCAN_COMPLETE_EVENT *ev;
1817
1818 ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
4f69cef0 1819 if ((int)ev->status == 0) {
30295c89
VM
1820 wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1821 }
1f4c34bd 1822 A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1071a134 1823 is_probe_ssid = false;
30295c89 1824
4f69cef0 1825 return 0;
30295c89
VM
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 */
1f4c34bd 1835static int
ab3655da 1836wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1854 return 0;
30295c89
VM
1855}
1856
1857
1f4c34bd 1858static int
ab3655da 1859wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1860{
1861 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1862
1863 A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
1864
4f69cef0 1865 return 0;
30295c89
VM
1866}
1867
1f4c34bd 1868static int
ab3655da 1869wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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];
ab3655da 1876 u8 upper_rssi_threshold, lower_rssi_threshold;
cb1e3709 1877 s16 rssi;
30295c89
VM
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
4f69cef0 1962 if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
30295c89
VM
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
4f69cef0 1969 return 0;
30295c89
VM
1970}
1971
1972
1f4c34bd 1973static int
ab3655da 1974wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 1986 return 0;
30295c89
VM
1987}
1988
1f4c34bd 1989static int
ab3655da 1990wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
1991{
1992 WMI_CAC_EVENT *reply;
1993 WMM_TSPEC_IE *tspec_ie;
4853ac05 1994 u16 activeTsids;
30295c89
VM
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) {
ab3655da 2011 u8 i;
30295c89
VM
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) {
ab3655da 2033 u8 tsid = 0;
30295c89
VM
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
4f69cef0 2056 return 0;
30295c89
VM
2057}
2058
1f4c34bd 2059static int
ab3655da 2060wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2073 return 0;
30295c89
VM
2074}
2075
1f4c34bd 2076static int
ab3655da 2077wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2089 return 0;
30295c89
VM
2090}
2091
1f4c34bd 2092static int
ab3655da 2093wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2105 return 0;
30295c89
VM
2106}
2107
1f4c34bd 2108static int
ab3655da 2109wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2121 return 0;
30295c89
VM
2122}
2123
1f4c34bd 2124static int
ab3655da 2125wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2134 return 0;
30295c89
VM
2135}
2136
1f4c34bd 2137static int
ab3655da 2138wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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;
ab3655da 2145 u8 upper_snr_threshold, lower_snr_threshold;
cb1e3709 2146 s16 snr;
30295c89
VM
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
4f69cef0 2221 if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
30295c89
VM
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
4f69cef0 2227 return 0;
30295c89
VM
2228}
2229
1f4c34bd 2230static int
ab3655da 2231wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2245 return 0;
30295c89
VM
2246}
2247
1f4c34bd 2248static int
ab3655da 2249wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89 2250{
4853ac05 2251 u16 ap_info_entry_size;
30295c89
VM
2252 WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2253 WMI_AP_INFO_V1 *ap_info_v1;
ab3655da 2254 u8 i;
30295c89
VM
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 }
4f69cef0 2286 return 0;
30295c89
VM
2287}
2288
1f4c34bd 2289static int
ab3655da 2290wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89 2291{
e1ce2a3a 2292 u32 dropped;
30295c89 2293
e1ce2a3a 2294 dropped = *((u32 *)datap);
30295c89
VM
2295 datap += sizeof(dropped);
2296 len -= sizeof(dropped);
f2ab1275 2297 A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
4f69cef0 2298 return 0;
30295c89
VM
2299}
2300
2301#ifdef CONFIG_HOST_GPIO_SUPPORT
1f4c34bd 2302static int
ab3655da 2303wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2313 return 0;
30295c89
VM
2314}
2315
1f4c34bd 2316static int
ab3655da 2317wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 2327 return 0;
30295c89
VM
2328}
2329
1f4c34bd 2330static int
ab3655da 2331wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
2332{
2333 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2334
2335 A_WMI_GPIO_ACK_RX();
2336
4f69cef0 2337 return 0;
30295c89
VM
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 */
1f4c34bd 2345int
30295c89
VM
2346wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2347 WMI_SYNC_FLAG syncflag)
2348{
1f4c34bd 2349 int status;
30295c89
VM
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
4f69cef0 2369 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
30295c89
VM
2370 A_NETBUF_FREE(osbuf);
2371 return A_NO_MEMORY;
2372 }
2373
2374 cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
4853ac05 2375 cHdr->commandId = (u16) cmdId;
30295c89
VM
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)) {
4f69cef0 2382 if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
30295c89
VM
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 }
4f69cef0 2397 return (0);
30295c89
VM
2398#undef IS_OPT_TX_CMD
2399}
2400
1f4c34bd 2401int
30295c89
VM
2402wmi_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
4f69cef0 2407 if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
30295c89
VM
2408 A_NETBUF_FREE(osbuf);
2409 return A_NO_MEMORY;
2410 }
2411
2412 cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
e1ce2a3a 2413 cHdr->commandId = (u32) cmdId;
30295c89
VM
2414
2415 return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2416}
2417
1f4c34bd 2418int
30295c89
VM
2419wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2420 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
ab3655da
JP
2421 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2422 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
d8cb316f 2423 int ssidLength, u8 *ssid,
e1ce2a3a 2424 u8 *bssid, u16 channel, u32 ctrl_flags)
30295c89
VM
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 {
05209262 2449 memcpy(cc->ssid, ssid, ssidLength);
30295c89
VM
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) {
05209262 2464 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
30295c89
VM
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
1f4c34bd 2473int
4853ac05 2474wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
30295c89
VM
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) {
05209262 2493 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
30295c89
VM
2494 }
2495
2496 return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
2497}
2498
1f4c34bd 2499int
30295c89
VM
2500wmi_disconnect_cmd(struct wmi_t *wmip)
2501{
1f4c34bd 2502 int status;
30295c89
VM
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
1f4c34bd 2512int
30295c89 2513wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
1071a134 2514 u32 forceFgScan, u32 isLegacy,
e1ce2a3a 2515 u32 homeDwellTime, u32 forceScanInterval,
f2ab1275 2516 s8 numChan, u16 *channelList)
30295c89
VM
2517{
2518 void *osbuf;
2519 WMI_START_SCAN_CMD *sc;
f2ab1275 2520 s8 size;
30295c89
VM
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 }
4853ac05 2532 size += sizeof(u16) * (numChan - 1);
30295c89
VM
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) {
05209262 2550 memcpy(sc->channelList, channelList, numChan * sizeof(u16));
30295c89
VM
2551 }
2552
2553 return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2554}
2555
1f4c34bd 2556int
4853ac05
JP
2557wmi_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,
ab3655da 2561 u8 shScanRatio, u8 scanCtrlFlags,
e1ce2a3a 2562 u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
30295c89
VM
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
1f4c34bd 2591int
e1ce2a3a 2592wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
30295c89
VM
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
1f4c34bd 2617int
ab3655da 2618wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
d8cb316f 2619 u8 ssidLength, u8 *ssid)
30295c89
VM
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) {
1071a134 2638 is_probe_ssid = true;
30295c89
VM
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;
05209262 2653 memcpy(cmd->ssid, ssid, ssidLength);
30295c89
VM
2654
2655 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
2656 NO_SYNC_WMIFLAG));
2657}
2658
1f4c34bd 2659int
4853ac05 2660wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
30295c89
VM
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
1f4c34bd 2681int
4853ac05 2682wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
30295c89
VM
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
1f4c34bd 2703int
ab3655da
JP
2704wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2705 u8 ieLen, u8 *ieInfo)
30295c89
VM
2706{
2707 void *osbuf;
2708 WMI_SET_ASSOC_INFO_CMD *cmd;
4853ac05 2709 u16 cmdLen;
30295c89
VM
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;
05209262 2723 memcpy(cmd->assocInfo, ieInfo, ieLen);
30295c89
VM
2724
2725 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
2726 NO_SYNC_WMIFLAG));
2727}
2728
1f4c34bd 2729int
ab3655da 2730wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
30295c89
VM
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
1f4c34bd 2751int
ab3655da 2752wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
4853ac05 2753 u16 atim_windows, u16 timeout_value)
30295c89
VM
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
1f4c34bd 2776int
e1ce2a3a
JP
2777wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2778 u32 ps_period, u8 sleep_period)
30295c89
VM
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
1f4c34bd 2801int
4853ac05
JP
2802wmi_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)
30295c89
VM
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
1f4c34bd 2830int
ab3655da 2831wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
30295c89
VM
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
1f4c34bd 2851int
ab3655da
JP
2852wmi_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,
30295c89
VM
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;
05209262 2883 memcpy(cmd->key, keyMaterial, keyLength);
30295c89
VM
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
05209262 2889 memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
30295c89
VM
2890 }
2891 cmd->key_op_ctrl = key_op_ctrl;
2892
2893 if(macAddr) {
05209262 2894 memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
30295c89
VM
2895 }
2896
2897 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
2898}
2899
1f4c34bd 2900int
ab3655da 2901wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
30295c89
VM
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));
05209262 2915 memcpy(cmd->krk, krk, WMI_KRK_LEN);
30295c89
VM
2916
2917 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
2918}
2919
1f4c34bd 2920int
30295c89
VM
2921wmi_delete_krk_cmd(struct wmi_t *wmip)
2922{
2923 return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2924}
2925
1f4c34bd 2926int
ab3655da 2927wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
30295c89
VM
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
1f4c34bd 2951int
ab3655da 2952wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
1071a134 2953 bool set)
30295c89
VM
2954{
2955 void *osbuf;
2956 WMI_SET_PMKID_CMD *cmd;
2957
2958 if (bssid == NULL) {
2959 return A_EINVAL;
2960 }
2961
1071a134 2962 if ((set == true) && (pmkId == NULL)) {
30295c89
VM
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));
05209262 2974 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
1071a134 2975 if (set == true) {
05209262 2976 memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
30295c89
VM
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
1f4c34bd 2986int
1071a134 2987wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
30295c89
VM
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));
1071a134 3000 cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
30295c89
VM
3001
3002 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
3003 NO_SYNC_WMIFLAG));
3004}
3005
1f4c34bd 3006int
30295c89
VM
3007wmi_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
1f4c34bd 3026int
30295c89
VM
3027wmi_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;
4853ac05 3032 u16 cmdLen;
ab3655da 3033 u8 i;
30295c89
VM
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++) {
05209262 3048 memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
30295c89
VM
3049 WMI_PMKID_LEN);
3050 }
3051
3052 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
3053 NO_SYNC_WMIFLAG));
3054}
3055
1f4c34bd 3056int
30295c89
VM
3057wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
3058{
3059 return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
3060}
3061
1f4c34bd 3062int
30295c89
VM
3063wmi_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
4f69cef0 3070 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
30295c89
VM
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
3083typedef struct _WMI_DATA_SYNC_BUFS {
ab3655da 3084 u8 trafficClass;
30295c89
VM
3085 void *osbuf;
3086}WMI_DATA_SYNC_BUFS;
3087
1f4c34bd 3088static int
30295c89
VM
3089wmi_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];
ab3655da 3094 u8 i,numPriStreams=0;
4f69cef0 3095 int status = 0;
30295c89
VM
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 */
391bb211 3147 if (status) {
30295c89
VM
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
391bb211 3158 if (status) {
30295c89
VM
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
391bb211 3173 if (status) {
30295c89
VM
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
1071a134 3181 } while(false);
30295c89
VM
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
1f4c34bd 3198int
30295c89
VM
3199wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
3200{
3201 void *osbuf;
3202 WMI_CREATE_PSTREAM_CMD *cmd;
ab3655da 3203 u8 fatPipeExistsForAC=0;
f68057e6
JP
3204 s32 minimalPHY = 0;
3205 s32 nominalPHY = 0;
30295c89
VM
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));
05209262 3261 memcpy(cmd, params, sizeof(*cmd));
30295c89
VM
3262
3263 /* this is an implicitly created Fat pipe */
e1ce2a3a 3264 if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
30295c89
VM
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
1f4c34bd 3294int
ab3655da 3295wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
30295c89
VM
3296{
3297 void *osbuf;
3298 WMI_DELETE_PSTREAM_CMD *cmd;
1f4c34bd 3299 int status;
4853ac05 3300 u16 activeTsids=0;
30295c89
VM
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
1f4c34bd 3358int
4853ac05 3359wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
30295c89
VM
3360{
3361 void *osbuf;
3362 WMI_FRAME_RATES_CMD *cmd;
ab3655da 3363 u8 frameType;
30295c89
VM
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
ab3655da 3384 frameType = (u8)((subType << 4) | type);
30295c89
VM
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 */
1f4c34bd 3397int
f68057e6 3398wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
30295c89
VM
3399{
3400 void *osbuf;
3401 WMI_BIT_RATE_CMD *cmd;
f2ab1275 3402 s8 drix, mrix, crix, ret_val;
30295c89
VM
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
1f4c34bd 3447int
30295c89
VM
3448wmi_get_bitrate_cmd(struct wmi_t *wmip)
3449{
3450 return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
3451}
3452
3453/*
1071a134 3454 * Returns true iff the given rate index is legal in the current PHY mode.
30295c89 3455 */
1071a134 3456bool
f68057e6 3457wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
30295c89
VM
3458{
3459 WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
1071a134 3460 bool isValid = true;
30295c89
VM
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)) {
1071a134 3465 isValid = false;
30295c89
VM
3466 }
3467 } else {
3468 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
1071a134 3469 isValid = false;
30295c89
VM
3470 }
3471 }
3472 break;
3473
3474 case WMI_11B_MODE:
3475 if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
1071a134 3476 isValid = false;
30295c89
VM
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)) {
1071a134 3483 isValid = false;
30295c89
VM
3484 }
3485 } else {
3486 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
1071a134 3487 isValid = false;
30295c89
VM
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)) {
1071a134 3496 isValid = false;
30295c89
VM
3497 }
3498 } else {
3499 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
1071a134 3500 isValid = false;
30295c89
VM
3501 }
3502 }
3503 break;
3504 default:
1071a134 3505 A_ASSERT(false);
30295c89
VM
3506 break;
3507 }
3508
3509 return isValid;
3510}
3511
f68057e6 3512s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
30295c89 3513{
f2ab1275 3514 s8 i;
30295c89
VM
3515
3516 for (i=0;;i++)
3517 {
e1ce2a3a 3518 if (wmi_rateTable[(u32) i][0] == 0) {
30295c89
VM
3519 return A_EINVAL;
3520 }
e1ce2a3a 3521 if (wmi_rateTable[(u32) i][0] == rate) {
30295c89
VM
3522 break;
3523 }
3524 }
3525
f68057e6 3526 if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
30295c89
VM
3527 return A_EINVAL;
3528 }
3529
3530 *rate_idx = i;
4f69cef0 3531 return 0;
30295c89
VM
3532}
3533
1f4c34bd 3534int
e1ce2a3a 3535wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
30295c89
VM
3536{
3537 void *osbuf;
3538 WMI_FIX_RATES_CMD *cmd;
3539#if 0
f68057e6 3540 s32 rateIndex;
30295c89
VM
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++) {
e1ce2a3a 3549 if((1 << rateIndex) & (u32)fixRatesMask) {
1071a134 3550 if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
30295c89
VM
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
1f4c34bd 3574int
30295c89
VM
3575wmi_get_ratemask_cmd(struct wmi_t *wmip)
3576{
3577 return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3578}
3579
1f4c34bd 3580int
30295c89
VM
3581wmi_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 */
1f4c34bd 3596int
ab3655da 3597wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
f2ab1275 3598 WMI_PHY_MODE mode, s8 numChan,
4853ac05 3599 u16 *channelList)
30295c89
VM
3600{
3601 void *osbuf;
3602 WMI_CHANNEL_PARAMS_CMD *cmd;
f2ab1275 3603 s8 size;
30295c89
VM
3604
3605 size = sizeof (*cmd);
3606
3607 if (numChan) {
3608 if (numChan > WMI_MAX_CHANNELS) {
3609 return A_EINVAL;
3610 }
4853ac05 3611 size += sizeof(u16) * (numChan - 1);
30295c89
VM
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;
05209262 3628 memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
30295c89
VM
3629
3630 return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3631 NO_SYNC_WMIFLAG));
3632}
3633
3634void
3635wmi_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
1f4c34bd 3683int
30295c89
VM
3684wmi_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
1f4c34bd 3708int
30295c89
VM
3709wmi_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 */
ab3655da
JP
3715 if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3716 (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
30295c89
VM
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));
05209262 3727 memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
30295c89
VM
3728
3729 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3730 NO_SYNC_WMIFLAG));
3731}
3732
1f4c34bd 3733int
30295c89
VM
3734wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3735 WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3736{
3737 void *osbuf;
f2ab1275 3738 s8 size;
30295c89 3739 WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
4853ac05 3740 u16 activeTsids=0;
ab3655da
JP
3741 u8 streamExists=0;
3742 u8 i;
30295c89
VM
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);
05209262 3759 memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
30295c89
VM
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
1f4c34bd 3795int
30295c89
VM
3796wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3797 WMI_SET_WOW_MODE_CMD *wowModeCmd)
3798{
3799 void *osbuf;
f2ab1275 3800 s8 size;
30295c89
VM
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);
05209262 3814 memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
30295c89
VM
3815
3816 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3817 NO_SYNC_WMIFLAG));
3818
3819}
3820
1f4c34bd 3821int
30295c89
VM
3822wmi_get_wow_list_cmd(struct wmi_t *wmip,
3823 WMI_GET_WOW_LIST_CMD *wowListCmd)
3824{
3825 void *osbuf;
f2ab1275 3826 s8 size;
30295c89
VM
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);
05209262 3840 memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
30295c89
VM
3841
3842 return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3843 NO_SYNC_WMIFLAG));
3844
3845}
3846
1f4c34bd 3847static int
ab3655da 3848wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 3860 return 0;
30295c89
VM
3861}
3862
1f4c34bd 3863int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
30295c89 3864 WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
ab3655da
JP
3865 u8 *pattern, u8 *mask,
3866 u8 pattern_size)
30295c89
VM
3867{
3868 void *osbuf;
f2ab1275 3869 s8 size;
30295c89 3870 WMI_ADD_WOW_PATTERN_CMD *cmd;
ab3655da 3871 u8 *filter_mask = NULL;
30295c89
VM
3872
3873 size = sizeof (*cmd);
3874
ab3655da 3875 size += ((2 * addWowCmd->filter_size)* sizeof(u8));
30295c89
VM
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
05209262 3888 memcpy(cmd->filter, pattern, addWowCmd->filter_size);
30295c89 3889
ab3655da 3890 filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
05209262 3891 memcpy(filter_mask, mask, addWowCmd->filter_size);
30295c89
VM
3892
3893
3894 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3895 NO_SYNC_WMIFLAG));
3896}
3897
1f4c34bd 3898int
30295c89
VM
3899wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3900 WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3901{
3902 void *osbuf;
f2ab1275 3903 s8 size;
30295c89
VM
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);
05209262 3917 memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
30295c89
VM
3918
3919 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3920 NO_SYNC_WMIFLAG));
3921
3922}
3923
3924void
3925wmi_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 */
ab3655da
JP
3955 snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3956 snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
30295c89
VM
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}
1f4c34bd 3969int
30295c89
VM
3970wmi_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
1f4c34bd 3986int
30295c89
VM
3987wmi_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
1f4c34bd 4000int
30295c89
VM
4001wmi_set_lq_threshold_params(struct wmi_t *wmip,
4002 WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
4003{
4004 void *osbuf;
f2ab1275 4005 s8 size;
30295c89
VM
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);
05209262 4029 memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
30295c89
VM
4030
4031 return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
4032 NO_SYNC_WMIFLAG));
4033}
4034
1f4c34bd 4035int
e1ce2a3a 4036wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
30295c89
VM
4037{
4038 void *osbuf;
f2ab1275 4039 s8 size;
30295c89
VM
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
1f4c34bd 4060int
e1ce2a3a 4061wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
30295c89
VM
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
1f4c34bd 4081int
4853ac05
JP
4082wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
4083 u16 tsr, bool rep, u16 size,
e1ce2a3a 4084 u32 valid)
30295c89
VM
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
1f4c34bd 4107int
30295c89
VM
4108wmi_get_stats_cmd(struct wmi_t *wmip)
4109{
4110 return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4111}
4112
1f4c34bd 4113int
ab3655da 4114wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
30295c89
VM
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;
05209262 4132 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
30295c89
VM
4133
4134 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4135}
4136
1f4c34bd 4137int
ab3655da 4138wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
30295c89
VM
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
1f4c34bd 4161int
30295c89
VM
4162wmi_abort_scan_cmd(struct wmi_t *wmip)
4163{
4164 return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4165}
4166
1f4c34bd 4167int
ab3655da 4168wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
30295c89
VM
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
1f4c34bd 4186int
30295c89
VM
4187wmi_get_txPwr_cmd(struct wmi_t *wmip)
4188{
4189 return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4190}
4191
4853ac05 4192u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
30295c89 4193{
4853ac05 4194 u16 activeTsids=0;
30295c89
VM
4195
4196 LOCK_WMI(wmip);
4197 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4198 UNLOCK_WMI(wmip);
4199
4200 return activeTsids;
4201}
4202
1f4c34bd 4203int
30295c89
VM
4204wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4205{
4206 return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4207}
4208
1f4c34bd 4209int
ab3655da 4210wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
30295c89
VM
4211{
4212 void *osbuf;
e1ce2a3a 4213 u32 size = sizeof(u8);
30295c89
VM
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
1f4c34bd 4230int
30295c89 4231wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
ab3655da 4232 u8 size)
30295c89
VM
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
05209262 4247 memcpy(cmd, p, size);
30295c89
VM
4248
4249 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4250 NO_SYNC_WMIFLAG));
4251}
4252
1f4c34bd 4253int
30295c89
VM
4254wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4255 WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
ab3655da 4256 u8 size)
30295c89
VM
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
05209262 4279 memcpy(cmd, pCmd, size);
30295c89
VM
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. */
1f4c34bd 4287int
30295c89 4288wmi_gpio_output_set(struct wmi_t *wmip,
e1ce2a3a
JP
4289 u32 set_mask,
4290 u32 clear_mask,
4291 u32 enable_mask,
4292 u32 disable_mask)
30295c89
VM
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 */
1f4c34bd 4321int
30295c89
VM
4322wmi_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. */
1f4c34bd 4330int
30295c89 4331wmi_gpio_register_set(struct wmi_t *wmip,
e1ce2a3a
JP
4332 u32 gpioreg_id,
4333 u32 value)
30295c89
VM
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. */
1f4c34bd 4359int
30295c89 4360wmi_gpio_register_get(struct wmi_t *wmip,
e1ce2a3a 4361 u32 gpioreg_id)
30295c89
VM
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. */
1f4c34bd 4385int
30295c89 4386wmi_gpio_intr_ack(struct wmi_t *wmip,
e1ce2a3a 4387 u32 ack_mask)
30295c89
VM
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
1f4c34bd 4411int
4853ac05 4412wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin,
ab3655da 4413 u8 eCWmax, u8 aifsn)
30295c89
VM
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
1f4c34bd 4442int
ab3655da
JP
4443wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4444 u8 trafficClass, u8 maxRetries,
4445 u8 enableNotify)
30295c89
VM
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
4481void
ab3655da 4482wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
30295c89
VM
4483{
4484 if (bssid != NULL) {
05209262 4485 memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
30295c89
VM
4486 }
4487}
4488
1f4c34bd 4489int
ab3655da 4490wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
30295c89
VM
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
1f4c34bd 4510int
30295c89 4511wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
ab3655da
JP
4512 u8 frmType,
4513 u8 *dstMacAddr,
4514 u8 *bssid,
4853ac05 4515 u16 optIEDataLen,
ab3655da 4516 u8 *optIEData)
30295c89
VM
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;
ab3655da 4532 //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd));
05209262
LR
4533 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4534 memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4535 memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
30295c89
VM
4536
4537 return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4538 NO_SYNC_WMIFLAG));
4539}
4540
1f4c34bd 4541int
4853ac05 4542wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
30295c89
VM
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
1f4c34bd 4563int
4853ac05 4564wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
30295c89
VM
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
1f4c34bd 4585int
ab3655da 4586wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
30295c89
VM
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
ab3655da
JP
4612u8 wmi_determine_userPriority(
4613 u8 *pkt,
e1ce2a3a 4614 u32 layer2Pri)
30295c89 4615{
ab3655da 4616 u8 ipPri;
30295c89
VM
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)
ab3655da 4632 return ((u8)layer2Pri & 0x7);
30295c89
VM
4633 else
4634 return ipPri;
4635}
4636
ab3655da 4637u8 convert_userPriority_to_trafficClass(u8 userPriority)
30295c89
VM
4638{
4639 return (up_to_ac[userPriority & 0x7]);
4640}
4641
ab3655da 4642u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
30295c89
VM
4643{
4644 return wmip->wmi_powerMode;
4645}
4646
1f4c34bd 4647int
8205669a 4648wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
30295c89 4649{
4f69cef0 4650 int ret = 0;
30295c89
VM
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
1f4c34bd 4680static int
ab3655da 4681wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 4688 return 0;
30295c89
VM
4689}
4690
4691#endif /* CONFIG_HOST_TCMD_SUPPORT*/
4692
1f4c34bd 4693int
ab3655da 4694wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
30295c89
VM
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
1f4c34bd 4714int
ab3655da 4715wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
30295c89
VM
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
1f4c34bd 4735int
ab3655da 4736wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
30295c89
VM
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
1f4c34bd 4757int
4853ac05 4758wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
30295c89
VM
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
1f4c34bd 4778int
30295c89
VM
4779wmi_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
1f4c34bd 4800int
ab3655da 4801wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
30295c89
VM
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
1f4c34bd 4821int
30295c89
VM
4822wmi_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
1f4c34bd 4846int
d8cb316f 4847wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
30295c89
VM
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));
05209262 4861 memcpy(cmd->countryCode,countryCode,3);
30295c89
VM
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
25985edc 4870 have different test command requirements from different manufacturers
30295c89 4871 */
1f4c34bd 4872int
e1ce2a3a 4873wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
30295c89
VM
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);
05209262 4887 memcpy(data, buf, len);
30295c89
VM
4888
4889 return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4890 NO_SYNC_WMIFLAG));
4891}
4892
4893#endif
4894
1f4c34bd 4895int
ab3655da 4896wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
30295c89
VM
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
1f4c34bd 4919int
30295c89
VM
4920wmi_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));
05209262 4975 memcpy(alloc_cmd, cmd, sizeof(*cmd));
30295c89
VM
4976
4977 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4978 NO_SYNC_WMIFLAG));
4979}
4980
1f4c34bd 4981int
30295c89
VM
4982wmi_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));
05209262 4994 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
30295c89
VM
4995 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4996 NO_SYNC_WMIFLAG));
4997
4998}
4999
5000
1f4c34bd 5001int
30295c89
VM
5002wmi_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));
05209262 5015 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
30295c89
VM
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
1f4c34bd 5022int
30295c89
VM
5023wmi_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));
05209262 5036 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
30295c89
VM
5037 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
5038 NO_SYNC_WMIFLAG));
5039
5040}
5041
1f4c34bd 5042int
30295c89
VM
5043wmi_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));
05209262 5056 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
30295c89
VM
5057 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
5058 NO_SYNC_WMIFLAG));
5059
5060}
5061
1f4c34bd 5062int
30295c89
VM
5063wmi_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));
05209262 5076 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
30295c89
VM
5077 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
5078 NO_SYNC_WMIFLAG));
5079
5080}
5081
1f4c34bd 5082int
30295c89
VM
5083wmi_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));
05209262 5096 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
30295c89
VM
5097 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
5098 NO_SYNC_WMIFLAG));
5099
5100}
5101
1f4c34bd 5102int
30295c89
VM
5103wmi_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));
05209262 5115 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
30295c89
VM
5116 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
5117 NO_SYNC_WMIFLAG));
5118
5119}
5120
1f4c34bd 5121int
30295c89
VM
5122wmi_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));
05209262 5135 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
30295c89
VM
5136 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
5137 NO_SYNC_WMIFLAG));
5138
5139}
5140
1f4c34bd 5141int
30295c89
VM
5142wmi_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));
05209262 5154 memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
30295c89
VM
5155 return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
5156 NO_SYNC_WMIFLAG));
5157
5158}
5159
1f4c34bd 5160int
30295c89
VM
5161wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
5162{
5163
5164 return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
5165
5166}
5167
1f4c34bd 5168int
30295c89
VM
5169wmi_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
ab3655da 5184u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
30295c89
VM
5185{
5186 return wmip->wmi_keepaliveInterval;
5187}
5188
1f4c34bd 5189int
ab3655da 5190wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
30295c89
VM
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
1f4c34bd 5211int
e1ce2a3a 5212wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
30295c89
VM
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;
05209262 5228 memcpy(cmd->buffer, buffer, length);
30295c89
VM
5229
5230 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5231 NO_SYNC_WMIFLAG));
5232}
5233
5234
1f4c34bd 5235int
ab3655da 5236wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
30295c89
VM
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
1f4c34bd 5261int
ab3655da 5262wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
30295c89
VM
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
1f4c34bd 5286int
ab3655da 5287wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
30295c89
VM
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
1f4c34bd 5306int
ab3655da
JP
5307wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5308 u8 *ieInfo)
30295c89
VM
5309{
5310 void *osbuf;
5311 WMI_SET_APPIE_CMD *cmd;
4853ac05 5312 u16 cmdLen;
30295c89
VM
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;
05209262 5327 memcpy(cmd->ieInfo, ieInfo, ieLen);
30295c89
VM
5328
5329 return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5330}
5331
1f4c34bd 5332int
4853ac05 5333wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
30295c89
VM
5334{
5335 void *osbuf;
ab3655da 5336 u8 *data;
30295c89
VM
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
05209262 5347 memcpy(data, cmd, dataLen);
30295c89
VM
5348
5349 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5350}
5351
f68057e6 5352s32 wmi_get_rate(s8 rateindex)
30295c89
VM
5353{
5354 if (rateindex == RATE_AUTO) {
5355 return 0;
5356 } else {
e1ce2a3a 5357 return(wmi_rateTable[(u32) rateindex][0]);
30295c89
VM
5358 }
5359}
5360
5361void
5362wmi_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
5370void
e1ce2a3a 5371wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
30295c89
VM
5372{
5373 wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5374}
5375
5376bss_t *
d8cb316f 5377wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
e1ce2a3a 5378 u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
30295c89
VM
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
5388void
5389wmi_refresh_scan_table (struct wmi_t *wmip)
5390{
5391 wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5392}
5393#endif
5394
5395void
5396wmi_free_allnodes(struct wmi_t *wmip)
5397{
5398 wlan_free_allnodes(&wmip->wmi_scan_table);
5399}
5400
5401bss_t *
ab3655da 5402wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
30295c89
VM
5403{
5404 bss_t *ni=NULL;
5405 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5406 return ni;
5407}
5408
5409void
ab3655da 5410wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
30295c89
VM
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
1f4c34bd 5422int
30295c89 5423wmi_dset_open_reply(struct wmi_t *wmip,
e1ce2a3a
JP
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)
30295c89
VM
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
1f4c34bd 5457static int
e1ce2a3a 5458wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
30295c89
VM
5459{
5460 WMI_PMKID_LIST_REPLY *reply;
e1ce2a3a 5461 u32 expected_len;
30295c89
VM
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
4f69cef0 5476 return 0;
30295c89
VM
5477}
5478
5479
1f4c34bd 5480static int
e1ce2a3a 5481wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
30295c89
VM
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
4f69cef0 5490 if (0 == reply->status)
30295c89
VM
5491 {
5492
5493 }
5494 else
5495 {
5496
5497 }
5498
4f69cef0 5499 return 0;
30295c89
VM
5500}
5501
5502
5503
1f4c34bd 5504static int
e1ce2a3a 5505wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
30295c89
VM
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);
4f69cef0 5512 return 0;
30295c89
VM
5513}
5514
5515
5516#ifdef CONFIG_HOST_DSET_SUPPORT
1f4c34bd 5517int
30295c89 5518wmi_dset_data_reply(struct wmi_t *wmip,
e1ce2a3a 5519 u32 status,
ab3655da 5520 u8 *user_buf,
e1ce2a3a
JP
5521 u32 length,
5522 u32 targ_buf,
5523 u32 targ_reply_fn,
5524 u32 targ_reply_arg)
30295c89
VM
5525{
5526 void *osbuf;
5527 WMIX_DSETDATA_REPLY_CMD *data_reply;
e1ce2a3a 5528 u32 size;
30295c89
VM
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
4f69cef0 5552 if (status == 0) {
30295c89
VM
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
1f4c34bd 5564int
e1ce2a3a 5565wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
30295c89
VM
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)
1f4c34bd 5588int
30295c89 5589wmi_prof_cfg_cmd(struct wmi_t *wmip,
e1ce2a3a
JP
5590 u32 period,
5591 u32 nbins)
30295c89
VM
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
1f4c34bd 5611int
e1ce2a3a 5612wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
30295c89
VM
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
1f4c34bd 5631int
30295c89
VM
5632wmi_prof_start_cmd(struct wmi_t *wmip)
5633{
5634 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5635}
5636
1f4c34bd 5637int
30295c89
VM
5638wmi_prof_stop_cmd(struct wmi_t *wmip)
5639{
5640 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5641}
5642
1f4c34bd 5643int
30295c89
VM
5644wmi_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 */
1f4c34bd 5650static int
ab3655da 5651wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 5661 return 0;
30295c89
VM
5662}
5663#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5664
5665#ifdef OS_ROAM_MANAGEMENT
5666
5667#define ETHERNET_MAC_ADDRESS_LENGTH 6
5668
5669void
5670wmi_scan_indication (struct wmi_t *wmip)
5671{
5672 struct ieee80211_node_table *nt;
e1ce2a3a
JP
5673 u32 gen;
5674 u32 size;
5675 u32 bsssize;
30295c89 5676 bss_t *bss;
e1ce2a3a 5677 u32 numbss;
30295c89
VM
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;
e1ce2a3a 5682 u32 RateSize;
30295c89
VM
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
cb1e3709 5884u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
e1ce2a3a 5885 u32 size)
30295c89 5886{
e1ce2a3a 5887 u32 index;
ab3655da 5888 u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
30295c89
VM
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]) {
ab3655da 5893 threshold = (u8)sq_thresh->upper_threshold[index];
30295c89
VM
5894 break;
5895 }
5896 }
5897
5898 return threshold;
5899}
5900
cb1e3709 5901u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
e1ce2a3a 5902 u32 size)
30295c89 5903{
e1ce2a3a 5904 u32 index;
ab3655da 5905 u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
30295c89
VM
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]) {
ab3655da 5910 threshold = (u8)sq_thresh->lower_threshold[index];
30295c89
VM
5911 break;
5912 }
5913 }
5914
5915 return threshold;
5916}
1f4c34bd 5917static int
30295c89
VM
5918wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5919 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5920{
5921 void *osbuf;
f2ab1275 5922 s8 size;
30295c89
VM
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);
05209262 5936 memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
30295c89
VM
5937
5938 return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5939 NO_SYNC_WMIFLAG));
5940}
1f4c34bd 5941static int
30295c89
VM
5942wmi_send_snr_threshold_params(struct wmi_t *wmip,
5943 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5944{
5945 void *osbuf;
f2ab1275 5946 s8 size;
30295c89
VM
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);
05209262 5959 memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
30295c89
VM
5960
5961 return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5962 NO_SYNC_WMIFLAG));
5963}
5964
1f4c34bd 5965int
30295c89
VM
5966wmi_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));
05209262 5980 memcpy(alloc_cmd, cmd, sizeof(*cmd));
30295c89
VM
5981
5982 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5983 NO_SYNC_WMIFLAG));
5984}
5985
ab3655da 5986bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
30295c89
VM
5987{
5988 wmi_get_current_bssid (wmip, id);
5989 return wlan_node_remove (&wmip->wmi_scan_table, id);
5990}
5991
ab3655da 5992int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
30295c89
VM
5993{
5994 wlan_setup_node (&wmip->wmi_scan_table, bss, id);
4f69cef0 5995 return 0;
30295c89
VM
5996}
5997
5998#ifdef ATH_AR6K_11N_SUPPORT
1f4c34bd 5999static int
ab3655da 6000wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 6006 return 0;
30295c89
VM
6007}
6008
6009
1f4c34bd 6010static int
ab3655da 6011wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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
4f69cef0 6017 return 0;
30295c89
VM
6018}
6019
1f4c34bd 6020static int
ab3655da 6021wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
6022{
6023 WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
6024
6025 A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
6026
4f69cef0 6027 return 0;
30295c89
VM
6028}
6029
1f4c34bd 6030int
ab3655da 6031wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
6032{
6033 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
6034
6035 A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
6036
4f69cef0 6037 return 0;
30295c89
VM
6038}
6039
6040
1f4c34bd 6041int
ab3655da 6042wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
30295c89
VM
6043{
6044 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
6045
6046 A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
6047
4f69cef0 6048 return 0;
30295c89
VM
6049
6050}
6051#endif
6052
1f4c34bd 6053static int
ab3655da 6054wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
6055{
6056 WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
6057 A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
6058
4f69cef0 6059 return 0;
30295c89
VM
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 */
1f4c34bd 6077int
30295c89
VM
6078wmi_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
05209262 6092 memcpy(cm,p,sizeof(*cm));
30295c89
VM
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 */
1f4c34bd 6103int
ab3655da 6104wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
30295c89
VM
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 */
1f4c34bd 6132int
ab3655da 6133wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
30295c89
VM
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 */
1f4c34bd 6160int
30295c89
VM
6161wmi_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));
05209262 6174 memcpy(a,acl,sizeof(*acl));
30295c89
VM
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 */
1f4c34bd 6186int
4853ac05 6187wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
30295c89
VM
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;
05209262 6202 memcpy(mlme->mac, mac, ATH_MAC_LEN);
30295c89
VM
6203 mlme->reason = reason;
6204
6205 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
6206}
6207
1f4c34bd 6208static int
ab3655da 6209wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
30295c89
VM
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);
4f69cef0 6219 return 0;
30295c89
VM
6220}
6221
1f4c34bd 6222static int
ab3655da 6223wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
30295c89
VM
6224{
6225 A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
4f69cef0 6226 return 0;
30295c89
VM
6227}
6228
6229#ifdef WAPI_ENABLE
1f4c34bd 6230static int
ab3655da 6231wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
30295c89 6232{
ab3655da 6233 u8 *ev;
30295c89
VM
6234
6235 if (len < 7) {
6236 return A_EINVAL;
6237 }
ab3655da 6238 ev = (u8 *)datap;
30295c89
VM
6239
6240 A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
4f69cef0 6241 return 0;
30295c89
VM
6242}
6243#endif
6244
1f4c34bd 6245int
4853ac05 6246wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
30295c89
VM
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
1f4c34bd 6266int
e1ce2a3a 6267wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
30295c89
VM
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
1f4c34bd 6286int
e1ce2a3a 6287wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
30295c89
VM
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
1f4c34bd 6307int
ab3655da 6308wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
30295c89
VM
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 */
1f4c34bd 6335int
ab3655da 6336wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
30295c89
VM
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
1f4c34bd 6355int
ab3655da 6356wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
30295c89
VM
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
1f4c34bd 6376int
30295c89
VM
6377wmi_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;
ab3655da 6381 u8 band;
30295c89
VM
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));
05209262 6395 memcpy(htCap, cmd, sizeof(*htCap));
30295c89
VM
6396
6397 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6398 NO_SYNC_WMIFLAG));
6399}
6400
1f4c34bd 6401int
ab3655da 6402wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
30295c89
VM
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
1f4c34bd 6423int
e1ce2a3a 6424wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
30295c89
VM
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));
05209262 6437 memcpy(pData, pMaskArray, sizeof(*pData));
30295c89
VM
6438
6439 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6440 NO_SYNC_WMIFLAG));
6441}
6442
6443
1f4c34bd 6444int
4853ac05 6445wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
30295c89
VM
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;
05209262 6459 memcpy(cmd->buf, buf, sz);
30295c89
VM
6460 return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6461}
6462
6463#ifdef ATH_AR6K_11N_SUPPORT
1f4c34bd 6464int
4853ac05 6465wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
30295c89
VM
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
1f4c34bd 6484int
ab3655da 6485wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
30295c89
VM
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
1f4c34bd 6503int
ab3655da 6504wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
30295c89
VM
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
1f4c34bd 6525int
ab3655da 6526wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
1071a134 6527 bool rxDot11Hdr, bool defragOnHost)
30295c89
VM
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));
1071a134
JP
6540 cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6541 cmd->defragOnHost = (defragOnHost==true)? 1:0;
30295c89
VM
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
1f4c34bd 6549int
1071a134 6550wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
30295c89
VM
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));
1071a134 6563 cmd->enable = (bThinMode==true)? 1:0;
30295c89
VM
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
1f4c34bd 6570int
30295c89
VM
6571wmi_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
1f4c34bd 6591int
ab3655da 6592wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
30295c89
VM
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
05209262 6607 memcpy(p->pmk, pmk, WMI_PMK_LEN);
30295c89
VM
6608
6609 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6610}
6611
711a1bcc
VM
6612int
6613wmi_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
1f4c34bd 6633int
e1ce2a3a 6634wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
30295c89
VM
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
6654bss_t *
d8cb316f 6655wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
e1ce2a3a
JP
6656 u32 ssidLength,
6657 u32 dot11AuthMode, u32 authMode,
6658 u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
30295c89
VM
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
4853ac05 6667u16 wmi_ieee2freq (int chan)
30295c89 6668{
4853ac05 6669 u16 freq = 0;
30295c89
VM
6670 freq = wlan_ieee2freq (chan);
6671 return freq;
6672
6673}
6674
e1ce2a3a 6675u32 wmi_freq2ieee (u16 freq)
30295c89 6676{
4853ac05 6677 u16 chan = 0;
30295c89
VM
6678 chan = wlan_freq2ieee (freq);
6679 return chan;
6680}