ath6kl: remove all the wext and super extended private ioctl crap
[linux-2.6.git] / drivers / staging / ath6kl / wmi / wmi.c
blob8b9ad76e70295ab609c2428e668cf90f5297ec91
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.
18 //------------------------------------------------------------------------------
19 //==============================================================================
20 // This module implements the hardware independent layer of the
21 // Wireless Module Interface (WMI) protocol.
23 // Author(s): ="Atheros"
24 //==============================================================================
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"
47 #define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
49 #ifdef ATH_DEBUG_MODULE
51 static struct ath_debug_mask_description wmi_debug_desc[] = {
52 { ATH_DEBUG_WMI , "General WMI Tracing"},
55 ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi,
56 "wmi",
57 "Wireless Module Interface",
58 ATH_DEBUG_MASK_DEFAULTS,
59 ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc),
60 wmi_debug_desc);
62 #endif
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
73 static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
75 static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
76 int len);
77 static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
78 int len);
80 static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
81 int len);
82 static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
83 int len);
84 static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
85 int len);
86 static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
87 int len);
88 static int wmi_sync_point(struct wmi_t *wmip);
90 static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
91 int len);
92 static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
93 int len);
94 static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
95 int len);
96 static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
97 int len);
98 static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
99 static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
100 int len);
102 static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
103 int len);
104 #ifdef CONFIG_HOST_DSET_SUPPORT
105 static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
106 static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
107 int len);
108 #endif /* CONFIG_HOST_DSET_SUPPORT */
111 static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
112 int len);
113 static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
114 static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
115 static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
116 static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
117 static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
118 static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
119 static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
120 static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
121 int len);
122 static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
123 int len);
124 static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
125 int len);
126 static int
127 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
129 static int
130 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
132 static int
133 wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
135 #ifdef CONFIG_HOST_TCMD_SUPPORT
136 static int
137 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
138 #endif
140 static int
141 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
143 static int
144 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
146 static int
147 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
149 static bool
150 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
152 static int
153 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
155 static int
156 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
158 static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
160 int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
161 WMI_SYNC_FLAG syncflag);
163 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
164 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
166 void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
167 void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
168 static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
169 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
170 static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
171 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
172 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
173 static int
174 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
175 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
177 static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
178 int len);
179 static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
180 int len);
182 static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
183 int len);
184 #ifdef ATH_AR6K_11N_SUPPORT
185 static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
186 static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
187 static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
188 static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
189 static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
190 #endif
191 static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
193 #ifdef WAPI_ENABLE
194 static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
195 int len);
196 #endif
198 #if defined(UNDER_CE)
199 #if defined(NDIS51_MINIPORT)
200 unsigned int processDot11Hdr = 0;
201 #else
202 unsigned int processDot11Hdr = 1;
203 #endif
204 #else
205 extern unsigned int processDot11Hdr;
206 #endif
208 int wps_enable;
209 static const s32 wmi_rateTable[][2] = {
210 //{W/O SGI, with SGI}
211 {1000, 1000},
212 {2000, 2000},
213 {5500, 5500},
214 {11000, 11000},
215 {6000, 6000},
216 {9000, 9000},
217 {12000, 12000},
218 {18000, 18000},
219 {24000, 24000},
220 {36000, 36000},
221 {48000, 48000},
222 {54000, 54000},
223 {6500, 7200},
224 {13000, 14400},
225 {19500, 21700},
226 {26000, 28900},
227 {39000, 43300},
228 {52000, 57800},
229 {58500, 65000},
230 {65000, 72200},
231 {13500, 15000},
232 {27000, 30000},
233 {40500, 45000},
234 {54000, 60000},
235 {81000, 90000},
236 {108000, 120000},
237 {121500, 135000},
238 {135000, 150000},
239 {0, 0}};
241 #define MODE_A_SUPPORT_RATE_START ((s32) 4)
242 #define MODE_A_SUPPORT_RATE_STOP ((s32) 11)
244 #define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
245 #define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
247 #define MODE_B_SUPPORT_RATE_START ((s32) 0)
248 #define MODE_B_SUPPORT_RATE_STOP ((s32) 3)
250 #define MODE_G_SUPPORT_RATE_START ((s32) 0)
251 #define MODE_G_SUPPORT_RATE_STOP ((s32) 11)
253 #define MODE_GHT20_SUPPORT_RATE_START ((s32) 0)
254 #define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19)
256 #define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1)
258 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
259 const u8 up_to_ac[]= {
260 WMM_AC_BE,
261 WMM_AC_BK,
262 WMM_AC_BK,
263 WMM_AC_BE,
264 WMM_AC_VI,
265 WMM_AC_VI,
266 WMM_AC_VO,
267 WMM_AC_VO,
270 #include "athstartpack.h"
272 /* This stuff is used when we want a simple layer-3 visibility */
273 typedef PREPACK struct _iphdr {
274 u8 ip_ver_hdrlen; /* version and hdr length */
275 u8 ip_tos; /* type of service */
276 u16 ip_len; /* total length */
277 u16 ip_id; /* identification */
278 s16 ip_off; /* fragment offset field */
279 #define IP_DF 0x4000 /* dont fragment flag */
280 #define IP_MF 0x2000 /* more fragments flag */
281 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
282 u8 ip_ttl; /* time to live */
283 u8 ip_p; /* protocol */
284 u16 ip_sum; /* checksum */
285 u8 ip_src[4]; /* source and dest address */
286 u8 ip_dst[4];
287 } POSTPACK iphdr;
289 #include "athendpack.h"
291 static s16 rssi_event_value = 0;
292 static s16 snr_event_value = 0;
294 bool is_probe_ssid = false;
296 void *
297 wmi_init(void *devt)
299 struct wmi_t *wmip;
301 A_REGISTER_MODULE_DEBUG_INFO(wmi);
303 wmip = A_MALLOC (sizeof(struct wmi_t));
304 if (wmip == NULL) {
305 return (NULL);
307 A_MEMZERO(wmip, sizeof(struct wmi_t ));
308 #ifdef THREAD_X
309 INIT_WMI_LOCK(wmip);
310 #else
311 A_MUTEX_INIT(&wmip->wmi_lock);
312 #endif
313 wmip->wmi_devt = devt;
314 wlan_node_table_init(wmip, &wmip->wmi_scan_table);
315 wmi_qos_state_init(wmip);
317 wmip->wmi_powerMode = REC_POWER;
318 wmip->wmi_phyMode = WMI_11G_MODE;
320 wmip->wmi_pair_crypto_type = NONE_CRYPT;
321 wmip->wmi_grp_crypto_type = NONE_CRYPT;
323 wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1;
324 wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1;
326 return (wmip);
329 void
330 wmi_qos_state_init(struct wmi_t *wmip)
332 u8 i;
334 if (wmip == NULL) {
335 return;
337 LOCK_WMI(wmip);
339 /* Initialize QoS States */
340 wmip->wmi_numQoSStream = 0;
342 wmip->wmi_fatPipeExists = 0;
344 for (i=0; i < WMM_NUM_AC; i++) {
345 wmip->wmi_streamExistsForAC[i]=0;
348 UNLOCK_WMI(wmip);
350 A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
353 void
354 wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid)
356 A_ASSERT( eid != ENDPOINT_UNUSED);
357 wmip->wmi_endpoint_id = eid;
360 HTC_ENDPOINT_ID
361 wmi_get_control_ep(struct wmi_t * wmip)
363 return(wmip->wmi_endpoint_id);
366 void
367 wmi_shutdown(struct wmi_t *wmip)
369 if (wmip != NULL) {
370 wlan_node_table_cleanup(&wmip->wmi_scan_table);
371 if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
372 #ifdef THREAD_X
373 DELETE_WMI_LOCK(&wmip);
374 #else
375 A_MUTEX_DELETE(&wmip->wmi_lock);
376 #endif
378 kfree(wmip);
383 * performs DIX to 802.3 encapsulation for transmit packets.
384 * uses passed in buffer. Returns buffer or NULL if failed.
385 * Assumes the entire DIX header is contigous and that there is
386 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
389 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
391 u8 *datap;
392 u16 typeorlen;
393 ATH_MAC_HDR macHdr;
394 ATH_LLC_SNAP_HDR *llcHdr;
396 A_ASSERT(osbuf != NULL);
398 if (A_NETBUF_HEADROOM(osbuf) <
399 (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
401 return A_NO_MEMORY;
404 datap = A_NETBUF_DATA(osbuf);
406 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
408 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
410 * packet is already in 802.3 format - return success
412 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
413 return (0);
417 * Save mac fields and length to be inserted later
419 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
420 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
421 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
422 sizeof(ATH_LLC_SNAP_HDR));
425 * Make room for LLC+SNAP headers
427 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
428 return A_NO_MEMORY;
430 datap = A_NETBUF_DATA(osbuf);
432 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
434 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
435 llcHdr->dsap = 0xAA;
436 llcHdr->ssap = 0xAA;
437 llcHdr->cntl = 0x03;
438 llcHdr->orgCode[0] = 0x0;
439 llcHdr->orgCode[1] = 0x0;
440 llcHdr->orgCode[2] = 0x0;
441 llcHdr->etherType = typeorlen;
443 return (0);
446 int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
448 switch(*pVersion){
449 case 0:
450 return (0);
451 case WMI_META_VERSION_1:
453 WMI_TX_META_V1 *pV1= NULL;
454 A_ASSERT(osbuf != NULL);
455 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
456 return A_NO_MEMORY;
459 pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf);
460 /* the pktID is used in conjunction with txComplete messages
461 * allowing the target to notify which tx requests have been
462 * completed and how. */
463 pV1->pktID = 0;
464 /* the ratePolicyID allows the host to specify which rate policy
465 * to use for transmitting this packet. 0 means use default behavior. */
466 pV1->ratePolicyID = 0;
467 A_ASSERT(pVersion != NULL);
468 /* the version must be used to populate the meta field of the WMI_DATA_HDR */
469 *pVersion = WMI_META_VERSION_1;
470 return (0);
472 #ifdef CONFIG_CHECKSUM_OFFLOAD
473 case WMI_META_VERSION_2:
475 WMI_TX_META_V2 *pV2 ;
476 A_ASSERT(osbuf != NULL);
477 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
478 return A_NO_MEMORY;
480 pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
481 memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
482 return (0);
484 #endif
485 default:
486 return (0);
490 /* Adds a WMI data header */
492 wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
493 WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
495 WMI_DATA_HDR *dtHdr;
496 // u8 metaVersion = 0;
497 int status;
499 A_ASSERT(osbuf != NULL);
501 /* adds the meta data field after the wmi data hdr. If metaVersion
502 * is returns 0 then no meta field was added. */
503 if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
504 return status;
507 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
508 return A_NO_MEMORY;
511 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
512 A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR));
514 WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType);
515 WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type);
517 if (bMoreData) {
518 WMI_DATA_HDR_SET_MORE_BIT(dtHdr);
521 WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
522 //dtHdr->rssi = 0;
524 return (0);
528 u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
530 u8 *datap;
531 u8 trafficClass = WMM_AC_BE;
532 u16 ipType = IP_ETHERTYPE;
533 WMI_DATA_HDR *dtHdr;
534 u8 streamExists = 0;
535 u8 userPriority;
536 u32 hdrsize, metasize;
537 ATH_LLC_SNAP_HDR *llcHdr;
539 WMI_CREATE_PSTREAM_CMD cmd;
541 A_ASSERT(osbuf != NULL);
544 // Initialize header size
546 hdrsize = 0;
548 datap = A_NETBUF_DATA(osbuf);
549 dtHdr = (WMI_DATA_HDR *)datap;
550 metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0;
552 if (!wmmEnabled)
554 /* If WMM is disabled all traffic goes as BE traffic */
555 userPriority = 0;
557 else
559 if (processDot11Hdr)
561 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
562 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
563 hdrsize);
567 else
569 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
570 sizeof(ATH_MAC_HDR));
573 if (llcHdr->etherType == A_CPU2BE16(ipType))
575 /* Extract the endpoint info from the TOS field in the IP header */
577 userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
579 else
581 userPriority = layer2Priority & 0x7;
586 /* workaround for WMM S5 */
587 if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority)))
589 userPriority = 1;
592 trafficClass = convert_userPriority_to_trafficClass(userPriority);
594 WMI_DATA_HDR_SET_UP(dtHdr, userPriority);
595 /* lower 3-bits are 802.1d priority */
596 //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;
598 LOCK_WMI(wmip);
599 streamExists = wmip->wmi_fatPipeExists;
600 UNLOCK_WMI(wmip);
602 if (!(streamExists & (1 << trafficClass)))
605 A_MEMZERO(&cmd, sizeof(cmd));
606 cmd.trafficClass = trafficClass;
607 cmd.userPriority = userPriority;
608 cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
609 /* Implicit streams are created with TSID 0xFF */
611 cmd.tsid = WMI_IMPLICIT_PSTREAM;
612 wmi_create_pstream_cmd(wmip, &cmd);
615 return trafficClass;
619 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
621 u8 *datap;
622 u16 typeorlen;
623 ATH_MAC_HDR macHdr;
624 ATH_LLC_SNAP_HDR *llcHdr;
625 struct ieee80211_frame *wh;
626 u32 hdrsize;
628 A_ASSERT(osbuf != NULL);
630 if (A_NETBUF_HEADROOM(osbuf) <
631 (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
633 return A_NO_MEMORY;
636 datap = A_NETBUF_DATA(osbuf);
638 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
640 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
642 * packet is already in 802.3 format - return success
644 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
645 goto AddDot11Hdr;
649 * Save mac fields and length to be inserted later
651 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
652 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
653 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
654 sizeof(ATH_LLC_SNAP_HDR));
656 // Remove the Ethernet hdr
657 A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR));
659 * Make room for LLC+SNAP headers
661 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
662 return A_NO_MEMORY;
664 datap = A_NETBUF_DATA(osbuf);
666 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
667 llcHdr->dsap = 0xAA;
668 llcHdr->ssap = 0xAA;
669 llcHdr->cntl = 0x03;
670 llcHdr->orgCode[0] = 0x0;
671 llcHdr->orgCode[1] = 0x0;
672 llcHdr->orgCode[2] = 0x0;
673 llcHdr->etherType = typeorlen;
675 AddDot11Hdr:
676 /* Make room for 802.11 hdr */
677 if (wmip->wmi_is_wmm_enabled)
679 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
680 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
682 return A_NO_MEMORY;
684 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
685 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS;
687 else
689 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
690 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
692 return A_NO_MEMORY;
694 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
695 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA;
697 /* Setup the SA & DA */
698 IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac);
700 if (mode == INFRA_NETWORK) {
701 IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac);
703 else if (mode == ADHOC_NETWORK) {
704 IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
707 return (0);
711 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
713 u8 *datap;
714 struct ieee80211_frame *pwh,wh;
715 u8 type,subtype;
716 ATH_LLC_SNAP_HDR *llcHdr;
717 ATH_MAC_HDR macHdr;
718 u32 hdrsize;
720 A_ASSERT(osbuf != NULL);
721 datap = A_NETBUF_DATA(osbuf);
723 pwh = (struct ieee80211_frame *)datap;
724 type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
725 subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
727 memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
729 /* strip off the 802.11 hdr*/
730 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
731 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
732 A_NETBUF_PULL(osbuf, hdrsize);
733 } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
734 A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
737 datap = A_NETBUF_DATA(osbuf);
738 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
740 macHdr.typeOrLen = llcHdr->etherType;
741 A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac));
742 A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac));
744 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
745 case IEEE80211_FC1_DIR_NODS:
746 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
747 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
748 break;
749 case IEEE80211_FC1_DIR_TODS:
750 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3);
751 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
752 break;
753 case IEEE80211_FC1_DIR_FROMDS:
754 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
755 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3);
756 break;
757 case IEEE80211_FC1_DIR_DSTODS:
758 break;
761 // Remove the LLC Hdr.
762 A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR));
764 // Insert the ATH MAC hdr.
766 A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
767 datap = A_NETBUF_DATA(osbuf);
769 memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
771 return 0;
775 * performs 802.3 to DIX encapsulation for received packets.
776 * Assumes the entire 802.3 header is contigous.
779 wmi_dot3_2_dix(void *osbuf)
781 u8 *datap;
782 ATH_MAC_HDR macHdr;
783 ATH_LLC_SNAP_HDR *llcHdr;
785 A_ASSERT(osbuf != NULL);
786 datap = A_NETBUF_DATA(osbuf);
788 memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
789 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
790 macHdr.typeOrLen = llcHdr->etherType;
792 if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
793 return A_NO_MEMORY;
796 datap = A_NETBUF_DATA(osbuf);
798 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
800 return (0);
804 * Removes a WMI data header
807 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
809 A_ASSERT(osbuf != NULL);
811 return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
814 void
815 wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
817 wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
821 * WMI Extended Event received from Target.
824 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
826 WMIX_CMD_HDR *cmd;
827 u16 id;
828 u8 *datap;
829 u32 len;
830 int status = 0;
832 if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
833 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
834 wmip->wmi_stats.cmd_len_err++;
835 return A_ERROR;
838 cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
839 id = cmd->commandId;
841 if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
842 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
843 wmip->wmi_stats.cmd_len_err++;
844 return A_ERROR;
847 datap = A_NETBUF_DATA(osbuf);
848 len = A_NETBUF_LEN(osbuf);
850 switch (id) {
851 case (WMIX_DSETOPENREQ_EVENTID):
852 status = wmi_dset_open_req_rx(wmip, datap, len);
853 break;
854 #ifdef CONFIG_HOST_DSET_SUPPORT
855 case (WMIX_DSETCLOSE_EVENTID):
856 status = wmi_dset_close_rx(wmip, datap, len);
857 break;
858 case (WMIX_DSETDATAREQ_EVENTID):
859 status = wmi_dset_data_req_rx(wmip, datap, len);
860 break;
861 #endif /* CONFIG_HOST_DSET_SUPPORT */
862 case (WMIX_HB_CHALLENGE_RESP_EVENTID):
863 wmi_hbChallengeResp_rx(wmip, datap, len);
864 break;
865 case (WMIX_DBGLOG_EVENTID):
866 wmi_dbglog_event_rx(wmip, datap, len);
867 break;
868 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
869 case (WMIX_PROF_COUNT_EVENTID):
870 wmi_prof_count_rx(wmip, datap, len);
871 break;
872 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
873 default:
874 A_DPRINTF(DBG_WMI|DBG_ERROR,
875 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
876 wmip->wmi_stats.cmd_id_err++;
877 status = A_ERROR;
878 break;
881 return status;
885 * Control Path
887 u32 cmdRecvNum;
890 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
892 WMI_CMD_HDR *cmd;
893 u16 id;
894 u8 *datap;
895 u32 len, i, loggingReq;
896 int status = 0;
898 A_ASSERT(osbuf != NULL);
899 if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
900 A_NETBUF_FREE(osbuf);
901 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
902 wmip->wmi_stats.cmd_len_err++;
903 return A_ERROR;
906 cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
907 id = cmd->commandId;
909 if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
910 A_NETBUF_FREE(osbuf);
911 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
912 wmip->wmi_stats.cmd_len_err++;
913 return A_ERROR;
916 datap = A_NETBUF_DATA(osbuf);
917 len = A_NETBUF_LEN(osbuf);
919 loggingReq = 0;
921 ar6000_get_driver_cfg(wmip->wmi_devt,
922 AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
923 &loggingReq);
925 if(loggingReq) {
926 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
927 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
928 for(i = 0; i < len; i++)
929 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
930 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
933 LOCK_WMI(wmip);
934 cmdRecvNum++;
935 UNLOCK_WMI(wmip);
937 switch (id) {
938 case (WMI_GET_BITRATE_CMDID):
939 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
940 status = wmi_bitrate_reply_rx(wmip, datap, len);
941 break;
942 case (WMI_GET_CHANNEL_LIST_CMDID):
943 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
944 status = wmi_channelList_reply_rx(wmip, datap, len);
945 break;
946 case (WMI_GET_TX_PWR_CMDID):
947 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
948 status = wmi_txPwr_reply_rx(wmip, datap, len);
949 break;
950 case (WMI_READY_EVENTID):
951 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
952 status = wmi_ready_event_rx(wmip, datap, len);
953 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
954 A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
955 break;
956 case (WMI_CONNECT_EVENTID):
957 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
958 status = wmi_connect_event_rx(wmip, datap, len);
959 A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
960 break;
961 case (WMI_DISCONNECT_EVENTID):
962 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
963 status = wmi_disconnect_event_rx(wmip, datap, len);
964 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
965 break;
966 case (WMI_PEER_NODE_EVENTID):
967 A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG));
968 status = wmi_peer_node_event_rx(wmip, datap, len);
969 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
970 break;
971 case (WMI_TKIP_MICERR_EVENTID):
972 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
973 status = wmi_tkip_micerr_event_rx(wmip, datap, len);
974 break;
975 case (WMI_BSSINFO_EVENTID):
976 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
979 * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR
980 * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer
981 * and reconstruct the WMI_BSS_INFO_HDR in its place
983 WMI_BSS_INFO_HDR2 bih2;
984 WMI_BSS_INFO_HDR *bih;
985 memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
987 A_NETBUF_PUSH(osbuf, 4);
988 datap = A_NETBUF_DATA(osbuf);
989 len = A_NETBUF_LEN(osbuf);
990 bih = (WMI_BSS_INFO_HDR *)datap;
992 bih->channel = bih2.channel;
993 bih->frameType = bih2.frameType;
994 bih->snr = bih2.snr;
995 bih->rssi = bih2.snr - 95;
996 bih->ieMask = bih2.ieMask;
997 memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
999 status = wmi_bssInfo_event_rx(wmip, datap, len);
1000 A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1002 break;
1003 case (WMI_REGDOMAIN_EVENTID):
1004 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
1005 status = wmi_regDomain_event_rx(wmip, datap, len);
1006 break;
1007 case (WMI_PSTREAM_TIMEOUT_EVENTID):
1008 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
1009 status = wmi_pstream_timeout_event_rx(wmip, datap, len);
1010 /* pstreams are fatpipe abstractions that get implicitly created.
1011 * User apps only deal with thinstreams. creation of a thinstream
1012 * by the user or data traffic flow in an AC triggers implicit
1013 * pstream creation. Do we need to send this event to App..?
1014 * no harm in sending it.
1016 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1017 break;
1018 case (WMI_NEIGHBOR_REPORT_EVENTID):
1019 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
1020 status = wmi_neighborReport_event_rx(wmip, datap, len);
1021 break;
1022 case (WMI_SCAN_COMPLETE_EVENTID):
1023 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
1024 status = wmi_scanComplete_rx(wmip, datap, len);
1025 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1026 break;
1027 case (WMI_CMDERROR_EVENTID):
1028 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
1029 status = wmi_errorEvent_rx(wmip, datap, len);
1030 break;
1031 case (WMI_REPORT_STATISTICS_EVENTID):
1032 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
1033 status = wmi_statsEvent_rx(wmip, datap, len);
1034 break;
1035 case (WMI_RSSI_THRESHOLD_EVENTID):
1036 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
1037 status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
1038 break;
1039 case (WMI_ERROR_REPORT_EVENTID):
1040 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
1041 status = wmi_reportErrorEvent_rx(wmip, datap, len);
1042 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1043 break;
1044 case (WMI_OPT_RX_FRAME_EVENTID):
1045 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
1046 status = wmi_opt_frame_event_rx(wmip, datap, len);
1047 break;
1048 case (WMI_REPORT_ROAM_TBL_EVENTID):
1049 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
1050 status = wmi_roam_tbl_event_rx(wmip, datap, len);
1051 break;
1052 case (WMI_EXTENSION_EVENTID):
1053 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
1054 status = wmi_control_rx_xtnd(wmip, osbuf);
1055 break;
1056 case (WMI_CAC_EVENTID):
1057 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
1058 status = wmi_cac_event_rx(wmip, datap, len);
1059 break;
1060 case (WMI_CHANNEL_CHANGE_EVENTID):
1061 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG));
1062 status = wmi_channel_change_event_rx(wmip, datap, len);
1063 break;
1064 case (WMI_REPORT_ROAM_DATA_EVENTID):
1065 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
1066 status = wmi_roam_data_event_rx(wmip, datap, len);
1067 break;
1068 #ifdef CONFIG_HOST_TCMD_SUPPORT
1069 case (WMI_TEST_EVENTID):
1070 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
1071 status = wmi_tcmd_test_report_rx(wmip, datap, len);
1072 break;
1073 #endif
1074 case (WMI_GET_FIXRATES_CMDID):
1075 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
1076 status = wmi_ratemask_reply_rx(wmip, datap, len);
1077 break;
1078 case (WMI_TX_RETRY_ERR_EVENTID):
1079 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
1080 status = wmi_txRetryErrEvent_rx(wmip, datap, len);
1081 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1082 break;
1083 case (WMI_SNR_THRESHOLD_EVENTID):
1084 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
1085 status = wmi_snrThresholdEvent_rx(wmip, datap, len);
1086 break;
1087 case (WMI_LQ_THRESHOLD_EVENTID):
1088 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
1089 status = wmi_lqThresholdEvent_rx(wmip, datap, len);
1090 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
1091 break;
1092 case (WMI_APLIST_EVENTID):
1093 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
1094 status = wmi_aplistEvent_rx(wmip, datap, len);
1095 break;
1096 case (WMI_GET_KEEPALIVE_CMDID):
1097 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
1098 status = wmi_keepalive_reply_rx(wmip, datap, len);
1099 break;
1100 case (WMI_GET_WOW_LIST_EVENTID):
1101 status = wmi_get_wow_list_event_rx(wmip, datap, len);
1102 break;
1103 case (WMI_GET_PMKID_LIST_EVENTID):
1104 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
1105 status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
1106 break;
1107 case (WMI_PSPOLL_EVENTID):
1108 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG));
1109 status = wmi_pspoll_event_rx(wmip, datap, len);
1110 break;
1111 case (WMI_DTIMEXPIRY_EVENTID):
1112 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG));
1113 status = wmi_dtimexpiry_event_rx(wmip, datap, len);
1114 break;
1115 case (WMI_SET_PARAMS_REPLY_EVENTID):
1116 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1117 status = wmi_set_params_event_rx(wmip, datap, len);
1118 break;
1119 case (WMI_ACM_REJECT_EVENTID):
1120 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1121 status = wmi_acm_reject_event_rx(wmip, datap, len);
1122 break;
1123 #ifdef ATH_AR6K_11N_SUPPORT
1124 case (WMI_ADDBA_REQ_EVENTID):
1125 status = wmi_addba_req_event_rx(wmip, datap, len);
1126 break;
1127 case (WMI_ADDBA_RESP_EVENTID):
1128 status = wmi_addba_resp_event_rx(wmip, datap, len);
1129 break;
1130 case (WMI_DELBA_REQ_EVENTID):
1131 status = wmi_delba_req_event_rx(wmip, datap, len);
1132 break;
1133 case (WMI_REPORT_BTCOEX_CONFIG_EVENTID):
1134 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG));
1135 status = wmi_btcoex_config_event_rx(wmip, datap, len);
1136 break;
1137 case (WMI_REPORT_BTCOEX_STATS_EVENTID):
1138 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG));
1139 status = wmi_btcoex_stats_event_rx(wmip, datap, len);
1140 break;
1141 #endif
1142 case (WMI_TX_COMPLETE_EVENTID):
1144 int index;
1145 TX_COMPLETE_MSG_V1 *pV1;
1146 WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap;
1147 A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType);
1149 for(index = 0 ; index < pEv->numMessages ; index++) {
1150 pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1));
1151 A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures);
1154 break;
1155 case (WMI_HCI_EVENT_EVENTID):
1156 status = wmi_hci_event_rx(wmip, datap, len);
1157 break;
1158 #ifdef WAPI_ENABLE
1159 case (WMI_WAPI_REKEY_EVENTID):
1160 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG));
1161 status = wmi_wapi_rekey_event_rx(wmip, datap, len);
1162 break;
1163 #endif
1164 default:
1165 A_DPRINTF(DBG_WMI|DBG_ERROR,
1166 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
1167 wmip->wmi_stats.cmd_id_err++;
1168 status = A_ERROR;
1169 break;
1172 A_NETBUF_FREE(osbuf);
1174 return status;
1177 /* Send a "simple" wmi command -- one with no arguments */
1178 static int
1179 wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
1181 void *osbuf;
1183 osbuf = A_NETBUF_ALLOC(0);
1184 if (osbuf == NULL) {
1185 return A_NO_MEMORY;
1188 return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1191 /* Send a "simple" extended wmi command -- one with no arguments.
1192 Enabling this command only if GPIO or profiling support is enabled.
1193 This is to suppress warnings on some platforms */
1194 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1195 static int
1196 wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
1198 void *osbuf;
1200 osbuf = A_NETBUF_ALLOC(0);
1201 if (osbuf == NULL) {
1202 return A_NO_MEMORY;
1205 return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1207 #endif
1209 static int
1210 wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1212 WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
1214 if (len < sizeof(WMI_READY_EVENT)) {
1215 return A_EINVAL;
1217 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1218 wmip->wmi_ready = true;
1219 A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
1220 ev->sw_version, ev->abi_version);
1222 return 0;
1225 #define LE_READ_4(p) \
1226 ((u32) \
1227 ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
1228 (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
1230 static int __inline
1231 iswmmoui(const u8 *frm)
1233 return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1236 static int __inline
1237 iswmmparam(const u8 *frm)
1239 return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1243 static int
1244 wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1246 WMI_CONNECT_EVENT *ev;
1247 u8 *pie,*peie;
1249 if (len < sizeof(WMI_CONNECT_EVENT))
1251 return A_EINVAL;
1253 ev = (WMI_CONNECT_EVENT *)datap;
1255 A_DPRINTF(DBG_WMI,
1256 (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
1257 DBGARG, ev->channel,
1258 ev->bssid[0], ev->bssid[1], ev->bssid[2],
1259 ev->bssid[3], ev->bssid[4], ev->bssid[5]));
1261 memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
1263 /* initialize pointer to start of assoc rsp IEs */
1264 pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
1265 sizeof(u16) + /* capinfo*/
1266 sizeof(u16) + /* status Code */
1267 sizeof(u16) ; /* associd */
1269 /* initialize pointer to end of assoc rsp IEs */
1270 peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
1272 while (pie < peie)
1274 switch (*pie)
1276 case IEEE80211_ELEMID_VENDOR:
1277 if (iswmmoui(pie))
1279 if(iswmmparam (pie))
1281 wmip->wmi_is_wmm_enabled = true;
1284 break;
1287 if (wmip->wmi_is_wmm_enabled)
1289 break;
1291 pie += pie[1] + 2;
1294 A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
1295 ev->listenInterval, ev->beaconInterval,
1296 (NETWORK_TYPE) ev->networkType, ev->beaconIeLen,
1297 ev->assocReqLen, ev->assocRespLen,
1298 ev->assocInfo);
1300 return 0;
1303 static int
1304 wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1306 WMI_REG_DOMAIN_EVENT *ev;
1308 if (len < sizeof(*ev)) {
1309 return A_EINVAL;
1311 ev = (WMI_REG_DOMAIN_EVENT *)datap;
1313 A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
1315 return 0;
1318 static int
1319 wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1321 WMI_NEIGHBOR_REPORT_EVENT *ev;
1322 int numAps;
1324 if (len < sizeof(*ev)) {
1325 return A_EINVAL;
1327 ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
1328 numAps = ev->numberOfAps;
1330 if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
1331 return A_EINVAL;
1334 A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
1336 return 0;
1339 static int
1340 wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1342 WMI_DISCONNECT_EVENT *ev;
1343 wmip->wmi_traffic_class = 100;
1345 if (len < sizeof(WMI_DISCONNECT_EVENT)) {
1346 return A_EINVAL;
1348 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1350 ev = (WMI_DISCONNECT_EVENT *)datap;
1352 A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
1354 wmip->wmi_is_wmm_enabled = false;
1355 wmip->wmi_pair_crypto_type = NONE_CRYPT;
1356 wmip->wmi_grp_crypto_type = NONE_CRYPT;
1358 A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
1359 ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
1361 return 0;
1364 static int
1365 wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1367 WMI_PEER_NODE_EVENT *ev;
1369 if (len < sizeof(WMI_PEER_NODE_EVENT)) {
1370 return A_EINVAL;
1372 ev = (WMI_PEER_NODE_EVENT *)datap;
1373 if (ev->eventCode == PEER_NODE_JOIN_EVENT) {
1374 A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG));
1375 } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) {
1376 A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG));
1379 A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
1381 return 0;
1384 static int
1385 wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1387 WMI_TKIP_MICERR_EVENT *ev;
1389 if (len < sizeof(*ev)) {
1390 return A_EINVAL;
1392 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1394 ev = (WMI_TKIP_MICERR_EVENT *)datap;
1395 A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
1397 return 0;
1400 static int
1401 wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1403 bss_t *bss = NULL;
1404 WMI_BSS_INFO_HDR *bih;
1405 u8 *buf;
1406 u32 nodeCachingAllowed = 1;
1407 u8 cached_ssid_len = 0;
1408 u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
1409 u8 beacon_ssid_len = 0;
1411 if (len <= sizeof(WMI_BSS_INFO_HDR)) {
1412 return A_EINVAL;
1415 bih = (WMI_BSS_INFO_HDR *)datap;
1416 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1418 if (bih->rssi > 0) {
1419 if (NULL == bss)
1420 return 0; //no node found in the table, just drop the node with incorrect RSSI
1421 else
1422 bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
1425 A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
1426 /* What is driver config for wlan node caching? */
1427 if(ar6000_get_driver_cfg(wmip->wmi_devt,
1428 AR6000_DRIVER_CFG_GET_WLANNODECACHING,
1429 &nodeCachingAllowed) != 0) {
1430 wmi_node_return(wmip, bss);
1431 return A_EINVAL;
1434 if(!nodeCachingAllowed) {
1435 wmi_node_return(wmip, bss);
1436 return 0;
1439 buf = datap + sizeof(WMI_BSS_INFO_HDR);
1440 len -= sizeof(WMI_BSS_INFO_HDR);
1442 A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
1443 "bssid \"%pM\"\n", DBGARG, bih->channel,
1444 (unsigned char) bih->rssi, bih->bssid));
1446 if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
1447 wmi_node_return(wmip, bss);
1448 return 0;
1451 if (bss != NULL) {
1453 * Free up the node. Not the most efficient process given
1454 * we are about to allocate a new node but it is simple and should be
1455 * adequate.
1458 /* In case of hidden AP, beacon will not have ssid,
1459 * but a directed probe response will have it,
1460 * so cache the probe-resp-ssid if already present. */
1461 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
1463 u8 *ie_ssid;
1465 ie_ssid = bss->ni_cie.ie_ssid;
1466 if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
1468 cached_ssid_len = ie_ssid[1];
1469 memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len);
1474 * Use the current average rssi of associated AP base on assumpiton
1475 * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically
1476 * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...)
1477 * The average value of RSSI give end-user better feeling for instance value of scan result
1478 * It also sync up RSSI info in GUI between scan result and RSSI signal icon
1480 if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
1481 bih->rssi = bss->ni_rssi;
1482 bih->snr = bss->ni_snr;
1485 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1488 /* beacon/probe response frame format
1489 * [8] time stamp
1490 * [2] beacon interval
1491 * [2] capability information
1492 * [tlv] ssid */
1493 beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
1495 /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
1496 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1497 (0 != cached_ssid_len) &&
1498 (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1500 len += (cached_ssid_len - beacon_ssid_len);
1503 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1504 if (bss == NULL) {
1505 return A_NO_MEMORY;
1508 bss->ni_snr = bih->snr;
1509 bss->ni_rssi = bih->rssi;
1510 A_ASSERT(bss->ni_buf != NULL);
1512 /* In case of hidden AP, beacon will not have ssid,
1513 * but a directed probe response will have it,
1514 * so place the cached-ssid(probe-resp) in the bssinfo. */
1515 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1516 (0 != cached_ssid_len) &&
1517 (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1519 u8 *ni_buf = bss->ni_buf;
1520 int buf_len = len;
1522 /* copy the first 14 bytes such as
1523 * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
1524 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
1526 ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
1527 ni_buf += (SSID_IE_LEN_INDEX + 1);
1529 buf += (SSID_IE_LEN_INDEX + 1);
1530 buf_len -= (SSID_IE_LEN_INDEX + 1);
1532 /* copy the cached ssid */
1533 memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
1534 ni_buf += cached_ssid_len;
1536 buf += beacon_ssid_len;
1537 buf_len -= beacon_ssid_len;
1539 if (cached_ssid_len > beacon_ssid_len)
1540 buf_len -= (cached_ssid_len - beacon_ssid_len);
1542 /* now copy the rest of bytes */
1543 memcpy(ni_buf, buf, buf_len);
1545 else
1546 memcpy(bss->ni_buf, buf, len);
1548 bss->ni_framelen = len;
1549 if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
1550 wlan_node_free(bss);
1551 return A_EINVAL;
1555 * Update the frequency in ie_chan, overwriting of channel number
1556 * which is done in wlan_parse_beacon
1558 bss->ni_cie.ie_chan = bih->channel;
1559 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1561 return 0;
1564 static int
1565 wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1567 bss_t *bss;
1568 WMI_OPT_RX_INFO_HDR *bih;
1569 u8 *buf;
1571 if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
1572 return A_EINVAL;
1575 bih = (WMI_OPT_RX_INFO_HDR *)datap;
1576 buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
1577 len -= sizeof(WMI_OPT_RX_INFO_HDR);
1579 A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
1580 bih->bssid[4], bih->bssid[5]));
1582 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1583 if (bss != NULL) {
1585 * Free up the node. Not the most efficient process given
1586 * we are about to allocate a new node but it is simple and should be
1587 * adequate.
1589 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1592 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1593 if (bss == NULL) {
1594 return A_NO_MEMORY;
1597 bss->ni_snr = bih->snr;
1598 bss->ni_cie.ie_chan = bih->channel;
1599 A_ASSERT(bss->ni_buf != NULL);
1600 memcpy(bss->ni_buf, buf, len);
1601 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1603 return 0;
1606 /* This event indicates inactivity timeout of a fatpipe(pstream)
1607 * at the target
1609 static int
1610 wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1612 WMI_PSTREAM_TIMEOUT_EVENT *ev;
1614 if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
1615 return A_EINVAL;
1618 A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
1620 ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
1622 /* When the pstream (fat pipe == AC) timesout, it means there were no
1623 * thinStreams within this pstream & it got implicitly created due to
1624 * data flow on this AC. We start the inactivity timer only for
1625 * implicitly created pstream. Just reset the host state.
1627 /* Set the activeTsids for this AC to 0 */
1628 LOCK_WMI(wmip);
1629 wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
1630 wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
1631 UNLOCK_WMI(wmip);
1633 /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
1634 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
1636 return 0;
1639 static int
1640 wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1642 WMI_BIT_RATE_REPLY *reply;
1643 s32 rate;
1644 u32 sgi,index;
1645 /* 54149:
1646 * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
1647 * since there is difference in the length and to avoid returning
1648 * error value.
1650 if (len < sizeof(WMI_BIT_RATE_REPLY)) {
1651 return A_EINVAL;
1653 reply = (WMI_BIT_RATE_REPLY *)datap;
1654 A_DPRINTF(DBG_WMI,
1655 (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
1657 if (reply->rateIndex == (s8) RATE_AUTO) {
1658 rate = RATE_AUTO;
1659 } else {
1660 // the SGI state is stored as the MSb of the rateIndex
1661 index = reply->rateIndex & 0x7f;
1662 sgi = (reply->rateIndex & 0x80)? 1:0;
1663 rate = wmi_rateTable[index][sgi];
1666 A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
1667 return 0;
1670 static int
1671 wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1673 WMI_FIX_RATES_REPLY *reply;
1675 if (len < sizeof(WMI_FIX_RATES_REPLY)) {
1676 return A_EINVAL;
1678 reply = (WMI_FIX_RATES_REPLY *)datap;
1679 A_DPRINTF(DBG_WMI,
1680 (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
1682 A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
1684 return 0;
1687 static int
1688 wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1690 WMI_CHANNEL_LIST_REPLY *reply;
1692 if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
1693 return A_EINVAL;
1695 reply = (WMI_CHANNEL_LIST_REPLY *)datap;
1696 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1698 A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
1699 reply->channelList);
1701 return 0;
1704 static int
1705 wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1707 WMI_TX_PWR_REPLY *reply;
1709 if (len < sizeof(*reply)) {
1710 return A_EINVAL;
1712 reply = (WMI_TX_PWR_REPLY *)datap;
1713 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1715 A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
1717 return 0;
1719 static int
1720 wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1722 WMI_GET_KEEPALIVE_CMD *reply;
1724 if (len < sizeof(*reply)) {
1725 return A_EINVAL;
1727 reply = (WMI_GET_KEEPALIVE_CMD *)datap;
1728 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1730 A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
1732 return 0;
1736 static int
1737 wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1739 WMIX_DSETOPENREQ_EVENT *dsetopenreq;
1741 if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
1742 return A_EINVAL;
1744 dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
1745 A_DPRINTF(DBG_WMI,
1746 (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
1747 A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
1748 dsetopenreq->dset_id,
1749 dsetopenreq->targ_dset_handle,
1750 dsetopenreq->targ_reply_fn,
1751 dsetopenreq->targ_reply_arg);
1753 return 0;
1756 #ifdef CONFIG_HOST_DSET_SUPPORT
1757 static int
1758 wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
1760 WMIX_DSETCLOSE_EVENT *dsetclose;
1762 if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
1763 return A_EINVAL;
1765 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1767 dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
1768 A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
1770 return 0;
1773 static int
1774 wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1776 WMIX_DSETDATAREQ_EVENT *dsetdatareq;
1778 if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
1779 return A_EINVAL;
1781 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1783 dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
1784 A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
1785 dsetdatareq->access_cookie,
1786 dsetdatareq->offset,
1787 dsetdatareq->length,
1788 dsetdatareq->targ_buf,
1789 dsetdatareq->targ_reply_fn,
1790 dsetdatareq->targ_reply_arg);
1792 return 0;
1794 #endif /* CONFIG_HOST_DSET_SUPPORT */
1796 static int
1797 wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
1799 WMI_SCAN_COMPLETE_EVENT *ev;
1801 ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1802 if ((int)ev->status == 0) {
1803 wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1805 A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1806 is_probe_ssid = false;
1808 return 0;
1812 * Target is reporting a programming error. This is for
1813 * developer aid only. Target only checks a few common violations
1814 * and it is responsibility of host to do all error checking.
1815 * Behavior of target after wmi error event is undefined.
1816 * A reset is recommended.
1818 static int
1819 wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1821 WMI_CMD_ERROR_EVENT *ev;
1823 ev = (WMI_CMD_ERROR_EVENT *)datap;
1824 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
1825 switch (ev->errorCode) {
1826 case (INVALID_PARAM):
1827 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
1828 break;
1829 case (ILLEGAL_STATE):
1830 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
1831 break;
1832 case (INTERNAL_ERROR):
1833 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
1834 break;
1837 return 0;
1841 static int
1842 wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1844 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1846 A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
1848 return 0;
1851 static int
1852 wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1854 WMI_RSSI_THRESHOLD_EVENT *reply;
1855 WMI_RSSI_THRESHOLD_VAL newThreshold;
1856 WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
1857 SQ_THRESHOLD_PARAMS *sq_thresh =
1858 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
1859 u8 upper_rssi_threshold, lower_rssi_threshold;
1860 s16 rssi;
1862 if (len < sizeof(*reply)) {
1863 return A_EINVAL;
1865 reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
1866 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1867 newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range;
1868 rssi = reply->rssi;
1871 * Identify the threshold breached and communicate that to the app. After
1872 * that install a new set of thresholds based on the signal quality
1873 * reported by the target
1875 if (newThreshold) {
1876 /* Upper threshold breached */
1877 if (rssi < sq_thresh->upper_threshold[0]) {
1878 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: "
1879 " %d\n", DBGARG, rssi));
1880 } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1881 (rssi >= sq_thresh->upper_threshold[0]))
1883 newThreshold = WMI_RSSI_THRESHOLD1_ABOVE;
1884 } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1885 (rssi >= sq_thresh->upper_threshold[1]))
1887 newThreshold = WMI_RSSI_THRESHOLD2_ABOVE;
1888 } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1889 (rssi >= sq_thresh->upper_threshold[2]))
1891 newThreshold = WMI_RSSI_THRESHOLD3_ABOVE;
1892 } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1893 (rssi >= sq_thresh->upper_threshold[3]))
1895 newThreshold = WMI_RSSI_THRESHOLD4_ABOVE;
1896 } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1897 (rssi >= sq_thresh->upper_threshold[4]))
1899 newThreshold = WMI_RSSI_THRESHOLD5_ABOVE;
1900 } else if (rssi >= sq_thresh->upper_threshold[5]) {
1901 newThreshold = WMI_RSSI_THRESHOLD6_ABOVE;
1903 } else {
1904 /* Lower threshold breached */
1905 if (rssi > sq_thresh->lower_threshold[0]) {
1906 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: "
1907 "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0]));
1908 } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1909 (rssi <= sq_thresh->lower_threshold[0]))
1911 newThreshold = WMI_RSSI_THRESHOLD6_BELOW;
1912 } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1913 (rssi <= sq_thresh->lower_threshold[1]))
1915 newThreshold = WMI_RSSI_THRESHOLD5_BELOW;
1916 } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1917 (rssi <= sq_thresh->lower_threshold[2]))
1919 newThreshold = WMI_RSSI_THRESHOLD4_BELOW;
1920 } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1921 (rssi <= sq_thresh->lower_threshold[3]))
1923 newThreshold = WMI_RSSI_THRESHOLD3_BELOW;
1924 } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1925 (rssi <= sq_thresh->lower_threshold[4]))
1927 newThreshold = WMI_RSSI_THRESHOLD2_BELOW;
1928 } else if (rssi <= sq_thresh->lower_threshold[5]) {
1929 newThreshold = WMI_RSSI_THRESHOLD1_BELOW;
1932 /* Calculate and install the next set of thresholds */
1933 lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh,
1934 sq_thresh->lower_threshold_valid_count);
1935 upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh,
1936 sq_thresh->upper_threshold_valid_count);
1937 /* Issue a wmi command to install the thresholds */
1938 cmd.thresholdAbove1_Val = upper_rssi_threshold;
1939 cmd.thresholdBelow1_Val = lower_rssi_threshold;
1940 cmd.weight = sq_thresh->weight;
1941 cmd.pollTime = sq_thresh->polling_interval;
1943 rssi_event_value = rssi;
1945 if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
1946 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
1947 DBGARG));
1950 A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
1952 return 0;
1956 static int
1957 wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1959 WMI_TARGET_ERROR_REPORT_EVENT *reply;
1961 if (len < sizeof(*reply)) {
1962 return A_EINVAL;
1964 reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
1965 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1967 A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
1969 return 0;
1972 static int
1973 wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1975 WMI_CAC_EVENT *reply;
1976 WMM_TSPEC_IE *tspec_ie;
1977 u16 activeTsids;
1979 if (len < sizeof(*reply)) {
1980 return A_EINVAL;
1982 reply = (WMI_CAC_EVENT *)datap;
1984 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1986 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1987 (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) {
1988 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1990 wmi_delete_pstream_cmd(wmip, reply->ac,
1991 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1993 else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1994 u8 i;
1996 /* following assumes that there is only one outstanding ADDTS request
1997 when this event is received */
1998 LOCK_WMI(wmip);
1999 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
2000 UNLOCK_WMI(wmip);
2002 for (i = 0; i < sizeof(activeTsids) * 8; i++) {
2003 if ((activeTsids >> i) & 1) {
2004 break;
2007 if (i < (sizeof(activeTsids) * 8)) {
2008 wmi_delete_pstream_cmd(wmip, reply->ac, i);
2012 * Ev#72990: Clear active tsids and Add missing handling
2013 * for delete qos stream from AP
2015 else if (reply->cac_indication == CAC_INDICATION_DELETE) {
2016 u8 tsid = 0;
2018 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
2019 tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
2020 LOCK_WMI(wmip);
2021 wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid);
2022 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
2023 UNLOCK_WMI(wmip);
2026 /* Indicate stream inactivity to driver layer only if all tsids
2027 * within this AC are deleted.
2029 if (!activeTsids) {
2030 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac);
2031 wmip->wmi_fatPipeExists &= ~(1 << reply->ac);
2035 A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
2036 reply->cac_indication, reply->statusCode,
2037 reply->tspecSuggestion);
2039 return 0;
2042 static int
2043 wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2045 WMI_CHANNEL_CHANGE_EVENT *reply;
2047 if (len < sizeof(*reply)) {
2048 return A_EINVAL;
2050 reply = (WMI_CHANNEL_CHANGE_EVENT *)datap;
2051 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2053 A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
2054 reply->newChannel);
2056 return 0;
2059 static int
2060 wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
2062 WMIX_HB_CHALLENGE_RESP_EVENT *reply;
2064 if (len < sizeof(*reply)) {
2065 return A_EINVAL;
2067 reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
2068 A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
2070 A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
2072 return 0;
2075 static int
2076 wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2078 WMI_TARGET_ROAM_TBL *reply;
2080 if (len < sizeof(*reply)) {
2081 return A_EINVAL;
2083 reply = (WMI_TARGET_ROAM_TBL *)datap;
2084 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2086 A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
2088 return 0;
2091 static int
2092 wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2094 WMI_TARGET_ROAM_DATA *reply;
2096 if (len < sizeof(*reply)) {
2097 return A_EINVAL;
2099 reply = (WMI_TARGET_ROAM_DATA *)datap;
2100 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2102 A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
2104 return 0;
2107 static int
2108 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2110 if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
2111 return A_EINVAL;
2113 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2115 A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
2117 return 0;
2120 static int
2121 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2123 WMI_SNR_THRESHOLD_EVENT *reply;
2124 SQ_THRESHOLD_PARAMS *sq_thresh =
2125 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
2126 WMI_SNR_THRESHOLD_VAL newThreshold;
2127 WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
2128 u8 upper_snr_threshold, lower_snr_threshold;
2129 s16 snr;
2131 if (len < sizeof(*reply)) {
2132 return A_EINVAL;
2134 reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
2135 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2137 newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range;
2138 snr = reply->snr;
2140 * Identify the threshold breached and communicate that to the app. After
2141 * that install a new set of thresholds based on the signal quality
2142 * reported by the target
2144 if (newThreshold) {
2145 /* Upper threshold breached */
2146 if (snr < sq_thresh->upper_threshold[0]) {
2147 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: "
2148 "%d\n", DBGARG, snr));
2149 } else if ((snr < sq_thresh->upper_threshold[1]) &&
2150 (snr >= sq_thresh->upper_threshold[0]))
2152 newThreshold = WMI_SNR_THRESHOLD1_ABOVE;
2153 } else if ((snr < sq_thresh->upper_threshold[2]) &&
2154 (snr >= sq_thresh->upper_threshold[1]))
2156 newThreshold = WMI_SNR_THRESHOLD2_ABOVE;
2157 } else if ((snr < sq_thresh->upper_threshold[3]) &&
2158 (snr >= sq_thresh->upper_threshold[2]))
2160 newThreshold = WMI_SNR_THRESHOLD3_ABOVE;
2161 } else if (snr >= sq_thresh->upper_threshold[3]) {
2162 newThreshold = WMI_SNR_THRESHOLD4_ABOVE;
2164 } else {
2165 /* Lower threshold breached */
2166 if (snr > sq_thresh->lower_threshold[0]) {
2167 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: "
2168 "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0]));
2169 } else if ((snr > sq_thresh->lower_threshold[1]) &&
2170 (snr <= sq_thresh->lower_threshold[0]))
2172 newThreshold = WMI_SNR_THRESHOLD4_BELOW;
2173 } else if ((snr > sq_thresh->lower_threshold[2]) &&
2174 (snr <= sq_thresh->lower_threshold[1]))
2176 newThreshold = WMI_SNR_THRESHOLD3_BELOW;
2177 } else if ((snr > sq_thresh->lower_threshold[3]) &&
2178 (snr <= sq_thresh->lower_threshold[2]))
2180 newThreshold = WMI_SNR_THRESHOLD2_BELOW;
2181 } else if (snr <= sq_thresh->lower_threshold[3]) {
2182 newThreshold = WMI_SNR_THRESHOLD1_BELOW;
2186 /* Calculate and install the next set of thresholds */
2187 lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh,
2188 sq_thresh->lower_threshold_valid_count);
2189 upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh,
2190 sq_thresh->upper_threshold_valid_count);
2192 /* Issue a wmi command to install the thresholds */
2193 cmd.thresholdAbove1_Val = upper_snr_threshold;
2194 cmd.thresholdBelow1_Val = lower_snr_threshold;
2195 cmd.weight = sq_thresh->weight;
2196 cmd.pollTime = sq_thresh->polling_interval;
2198 A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n"
2199 ,DBGARG, snr, newThreshold, lower_snr_threshold,
2200 upper_snr_threshold));
2202 snr_event_value = snr;
2204 if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
2205 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
2206 DBGARG));
2208 A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
2210 return 0;
2213 static int
2214 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2216 WMI_LQ_THRESHOLD_EVENT *reply;
2218 if (len < sizeof(*reply)) {
2219 return A_EINVAL;
2221 reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
2222 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2224 A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt,
2225 (WMI_LQ_THRESHOLD_VAL) reply->range,
2226 reply->lq);
2228 return 0;
2231 static int
2232 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2234 u16 ap_info_entry_size;
2235 WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2236 WMI_AP_INFO_V1 *ap_info_v1;
2237 u8 i;
2239 if (len < sizeof(WMI_APLIST_EVENT)) {
2240 return A_EINVAL;
2243 if (ev->apListVer == APLIST_VER1) {
2244 ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
2245 ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
2246 } else {
2247 return A_EINVAL;
2250 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
2251 if (len < (int)(sizeof(WMI_APLIST_EVENT) +
2252 (ev->numAP - 1) * ap_info_entry_size))
2254 return A_EINVAL;
2258 * AP List Ver1 Contents
2260 for (i = 0; i < ev->numAP; i++) {
2261 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
2262 "Channel %d\n", i,
2263 ap_info_v1->bssid[0], ap_info_v1->bssid[1],
2264 ap_info_v1->bssid[2], ap_info_v1->bssid[3],
2265 ap_info_v1->bssid[4], ap_info_v1->bssid[5],
2266 ap_info_v1->channel));
2267 ap_info_v1++;
2269 return 0;
2272 static int
2273 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2275 u32 dropped;
2277 dropped = *((u32 *)datap);
2278 datap += sizeof(dropped);
2279 len -= sizeof(dropped);
2280 A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
2281 return 0;
2285 * Called to send a wmi command. Command specific data is already built
2286 * on osbuf and current osbuf->data points to it.
2289 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2290 WMI_SYNC_FLAG syncflag)
2292 int status;
2293 #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
2294 WMI_CMD_HDR *cHdr;
2295 HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id;
2297 A_ASSERT(osbuf != NULL);
2299 if (syncflag >= END_WMIFLAG) {
2300 A_NETBUF_FREE(osbuf);
2301 return A_EINVAL;
2304 if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2306 * We want to make sure all data currently queued is transmitted before
2307 * the cmd execution. Establish a new sync point.
2309 wmi_sync_point(wmip);
2312 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
2313 A_NETBUF_FREE(osbuf);
2314 return A_NO_MEMORY;
2317 cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
2318 cHdr->commandId = (u16) cmdId;
2319 cHdr->info1 = 0; // added for virtual interface
2322 * Only for OPT_TX_CMD, use BE endpoint.
2324 if (IS_OPT_TX_CMD(cmdId)) {
2325 if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
2326 A_NETBUF_FREE(osbuf);
2327 return status;
2329 eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE);
2331 A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid);
2333 if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2335 * We want to make sure all new data queued waits for the command to
2336 * execute. Establish a new sync point.
2338 wmi_sync_point(wmip);
2340 return (0);
2341 #undef IS_OPT_TX_CMD
2345 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
2346 WMI_SYNC_FLAG syncflag)
2348 WMIX_CMD_HDR *cHdr;
2350 if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
2351 A_NETBUF_FREE(osbuf);
2352 return A_NO_MEMORY;
2355 cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
2356 cHdr->commandId = (u32) cmdId;
2358 return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2362 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2363 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
2364 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2365 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
2366 int ssidLength, u8 *ssid,
2367 u8 *bssid, u16 channel, u32 ctrl_flags)
2369 void *osbuf;
2370 WMI_CONNECT_CMD *cc;
2371 wmip->wmi_traffic_class = 100;
2373 if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
2374 return A_EINVAL;
2376 if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
2377 return A_EINVAL;
2380 osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
2381 if (osbuf == NULL) {
2382 return A_NO_MEMORY;
2385 A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
2387 cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2388 A_MEMZERO(cc, sizeof(*cc));
2390 if (ssidLength)
2392 memcpy(cc->ssid, ssid, ssidLength);
2395 cc->ssidLength = ssidLength;
2396 cc->networkType = netType;
2397 cc->dot11AuthMode = dot11AuthMode;
2398 cc->authMode = authMode;
2399 cc->pairwiseCryptoType = pairwiseCrypto;
2400 cc->pairwiseCryptoLen = pairwiseCryptoLen;
2401 cc->groupCryptoType = groupCrypto;
2402 cc->groupCryptoLen = groupCryptoLen;
2403 cc->channel = channel;
2404 cc->ctrl_flags = ctrl_flags;
2406 if (bssid != NULL) {
2407 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2410 wmip->wmi_pair_crypto_type = pairwiseCrypto;
2411 wmip->wmi_grp_crypto_type = groupCrypto;
2413 return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
2417 wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
2419 void *osbuf;
2420 WMI_RECONNECT_CMD *cc;
2421 wmip->wmi_traffic_class = 100;
2423 osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
2424 if (osbuf == NULL) {
2425 return A_NO_MEMORY;
2428 A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
2430 cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2431 A_MEMZERO(cc, sizeof(*cc));
2433 cc->channel = channel;
2435 if (bssid != NULL) {
2436 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2439 return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
2443 wmi_disconnect_cmd(struct wmi_t *wmip)
2445 int status;
2446 wmip->wmi_traffic_class = 100;
2448 /* Bug fix for 24817(elevator bug) - the disconnect command does not
2449 need to do a SYNC before.*/
2450 status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID);
2452 return status;
2456 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
2457 u32 forceFgScan, u32 isLegacy,
2458 u32 homeDwellTime, u32 forceScanInterval,
2459 s8 numChan, u16 *channelList)
2461 void *osbuf;
2462 WMI_START_SCAN_CMD *sc;
2463 s8 size;
2465 size = sizeof (*sc);
2467 if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
2468 return A_EINVAL;
2471 if (numChan) {
2472 if (numChan > WMI_MAX_CHANNELS) {
2473 return A_EINVAL;
2475 size += sizeof(u16) * (numChan - 1);
2478 osbuf = A_NETBUF_ALLOC(size);
2479 if (osbuf == NULL) {
2480 return A_NO_MEMORY;
2483 A_NETBUF_PUT(osbuf, size);
2485 sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
2486 sc->scanType = scanType;
2487 sc->forceFgScan = forceFgScan;
2488 sc->isLegacy = isLegacy;
2489 sc->homeDwellTime = homeDwellTime;
2490 sc->forceScanInterval = forceScanInterval;
2491 sc->numChannels = numChan;
2492 if (numChan) {
2493 memcpy(sc->channelList, channelList, numChan * sizeof(u16));
2496 return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2500 wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
2501 u16 fg_end_sec, u16 bg_sec,
2502 u16 minact_chdw_msec, u16 maxact_chdw_msec,
2503 u16 pas_chdw_msec,
2504 u8 shScanRatio, u8 scanCtrlFlags,
2505 u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
2507 void *osbuf;
2508 WMI_SCAN_PARAMS_CMD *sc;
2510 osbuf = A_NETBUF_ALLOC(sizeof(*sc));
2511 if (osbuf == NULL) {
2512 return A_NO_MEMORY;
2515 A_NETBUF_PUT(osbuf, sizeof(*sc));
2517 sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2518 A_MEMZERO(sc, sizeof(*sc));
2519 sc->fg_start_period = fg_start_sec;
2520 sc->fg_end_period = fg_end_sec;
2521 sc->bg_period = bg_sec;
2522 sc->minact_chdwell_time = minact_chdw_msec;
2523 sc->maxact_chdwell_time = maxact_chdw_msec;
2524 sc->pas_chdwell_time = pas_chdw_msec;
2525 sc->shortScanRatio = shScanRatio;
2526 sc->scanCtrlFlags = scanCtrlFlags;
2527 sc->max_dfsch_act_time = max_dfsch_act_time;
2528 sc->maxact_scan_per_ssid = maxact_scan_per_ssid;
2530 return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
2531 NO_SYNC_WMIFLAG));
2535 wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
2537 void *osbuf;
2538 WMI_BSS_FILTER_CMD *cmd;
2540 if (filter >= LAST_BSS_FILTER) {
2541 return A_EINVAL;
2544 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2545 if (osbuf == NULL) {
2546 return A_NO_MEMORY;
2549 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2551 cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
2552 A_MEMZERO(cmd, sizeof(*cmd));
2553 cmd->bssFilter = filter;
2554 cmd->ieMask = ieMask;
2556 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
2557 NO_SYNC_WMIFLAG));
2561 wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
2562 u8 ssidLength, u8 *ssid)
2564 void *osbuf;
2565 WMI_PROBED_SSID_CMD *cmd;
2567 if (index > MAX_PROBED_SSID_INDEX) {
2568 return A_EINVAL;
2570 if (ssidLength > sizeof(cmd->ssid)) {
2571 return A_EINVAL;
2573 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
2574 return A_EINVAL;
2576 if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
2577 return A_EINVAL;
2580 if (flag & SPECIFIC_SSID_FLAG) {
2581 is_probe_ssid = true;
2584 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2585 if (osbuf == NULL) {
2586 return A_NO_MEMORY;
2589 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2591 cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
2592 A_MEMZERO(cmd, sizeof(*cmd));
2593 cmd->entryIndex = index;
2594 cmd->flag = flag;
2595 cmd->ssidLength = ssidLength;
2596 memcpy(cmd->ssid, ssid, ssidLength);
2598 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
2599 NO_SYNC_WMIFLAG));
2603 wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
2605 void *osbuf;
2606 WMI_LISTEN_INT_CMD *cmd;
2608 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2609 if (osbuf == NULL) {
2610 return A_NO_MEMORY;
2613 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2615 cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
2616 A_MEMZERO(cmd, sizeof(*cmd));
2617 cmd->listenInterval = listenInterval;
2618 cmd->numBeacons = listenBeacons;
2620 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
2621 NO_SYNC_WMIFLAG));
2625 wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
2627 void *osbuf;
2628 WMI_BMISS_TIME_CMD *cmd;
2630 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2631 if (osbuf == NULL) {
2632 return A_NO_MEMORY;
2635 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2637 cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
2638 A_MEMZERO(cmd, sizeof(*cmd));
2639 cmd->bmissTime = bmissTime;
2640 cmd->numBeacons = bmissBeacons;
2642 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
2643 NO_SYNC_WMIFLAG));
2647 wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2648 u8 ieLen, u8 *ieInfo)
2650 void *osbuf;
2651 WMI_SET_ASSOC_INFO_CMD *cmd;
2652 u16 cmdLen;
2654 cmdLen = sizeof(*cmd) + ieLen - 1;
2655 osbuf = A_NETBUF_ALLOC(cmdLen);
2656 if (osbuf == NULL) {
2657 return A_NO_MEMORY;
2660 A_NETBUF_PUT(osbuf, cmdLen);
2662 cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
2663 A_MEMZERO(cmd, cmdLen);
2664 cmd->ieType = ieType;
2665 cmd->bufferSize = ieLen;
2666 memcpy(cmd->assocInfo, ieInfo, ieLen);
2668 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
2669 NO_SYNC_WMIFLAG));
2673 wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
2675 void *osbuf;
2676 WMI_POWER_MODE_CMD *cmd;
2678 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2679 if (osbuf == NULL) {
2680 return A_NO_MEMORY;
2683 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2685 cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2686 A_MEMZERO(cmd, sizeof(*cmd));
2687 cmd->powerMode = powerMode;
2688 wmip->wmi_powerMode = powerMode;
2690 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
2691 NO_SYNC_WMIFLAG));
2695 wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
2696 u16 atim_windows, u16 timeout_value)
2698 void *osbuf;
2699 WMI_IBSS_PM_CAPS_CMD *cmd;
2701 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2702 if (osbuf == NULL) {
2703 return A_NO_MEMORY;
2706 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2708 cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
2709 A_MEMZERO(cmd, sizeof(*cmd));
2710 cmd->power_saving = pmEnable;
2711 cmd->ttl = ttl;
2712 cmd->atim_windows = atim_windows;
2713 cmd->timeout_value = timeout_value;
2715 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
2716 NO_SYNC_WMIFLAG));
2720 wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2721 u32 ps_period, u8 sleep_period)
2723 void *osbuf;
2724 WMI_AP_PS_CMD *cmd;
2726 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2727 if (osbuf == NULL) {
2728 return A_NO_MEMORY;
2731 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2733 cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf));
2734 A_MEMZERO(cmd, sizeof(*cmd));
2735 cmd->psType = psType;
2736 cmd->idle_time = idle_time;
2737 cmd->ps_period = ps_period;
2738 cmd->sleep_period = sleep_period;
2740 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID,
2741 NO_SYNC_WMIFLAG));
2745 wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
2746 u16 psPollNum, u16 dtimPolicy,
2747 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2748 u16 ps_fail_event_policy)
2750 void *osbuf;
2751 WMI_POWER_PARAMS_CMD *pm;
2753 osbuf = A_NETBUF_ALLOC(sizeof(*pm));
2754 if (osbuf == NULL) {
2755 return A_NO_MEMORY;
2758 A_NETBUF_PUT(osbuf, sizeof(*pm));
2760 pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2761 A_MEMZERO(pm, sizeof(*pm));
2762 pm->idle_period = idlePeriod;
2763 pm->pspoll_number = psPollNum;
2764 pm->dtim_policy = dtimPolicy;
2765 pm->tx_wakeup_policy = tx_wakeup_policy;
2766 pm->num_tx_to_wakeup = num_tx_to_wakeup;
2767 pm->ps_fail_event_policy = ps_fail_event_policy;
2769 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
2770 NO_SYNC_WMIFLAG));
2774 wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
2776 void *osbuf;
2777 WMI_DISC_TIMEOUT_CMD *cmd;
2779 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2780 if (osbuf == NULL) {
2781 return A_NO_MEMORY;
2784 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2786 cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
2787 A_MEMZERO(cmd, sizeof(*cmd));
2788 cmd->disconnectTimeout = timeout;
2790 return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
2791 NO_SYNC_WMIFLAG));
2795 wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
2796 u8 keyUsage, u8 keyLength, u8 *keyRSC,
2797 u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
2798 WMI_SYNC_FLAG sync_flag)
2800 void *osbuf;
2801 WMI_ADD_CIPHER_KEY_CMD *cmd;
2803 if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
2804 (keyMaterial == NULL))
2806 return A_EINVAL;
2809 if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
2810 return A_EINVAL;
2813 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2814 if (osbuf == NULL) {
2815 return A_NO_MEMORY;
2818 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2820 cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2821 A_MEMZERO(cmd, sizeof(*cmd));
2822 cmd->keyIndex = keyIndex;
2823 cmd->keyType = keyType;
2824 cmd->keyUsage = keyUsage;
2825 cmd->keyLength = keyLength;
2826 memcpy(cmd->key, keyMaterial, keyLength);
2827 #ifdef WAPI_ENABLE
2828 if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
2829 #else
2830 if (NULL != keyRSC) {
2831 #endif // WAPI_ENABLE
2832 memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
2834 cmd->key_op_ctrl = key_op_ctrl;
2836 if(macAddr) {
2837 memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
2840 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
2844 wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
2846 void *osbuf;
2847 WMI_ADD_KRK_CMD *cmd;
2849 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2850 if (osbuf == NULL) {
2851 return A_NO_MEMORY;
2854 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2856 cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
2857 A_MEMZERO(cmd, sizeof(*cmd));
2858 memcpy(cmd->krk, krk, WMI_KRK_LEN);
2860 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
2864 wmi_delete_krk_cmd(struct wmi_t *wmip)
2866 return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2870 wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
2872 void *osbuf;
2873 WMI_DELETE_CIPHER_KEY_CMD *cmd;
2875 if (keyIndex > WMI_MAX_KEY_INDEX) {
2876 return A_EINVAL;
2879 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2880 if (osbuf == NULL) {
2881 return A_NO_MEMORY;
2884 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2886 cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2887 A_MEMZERO(cmd, sizeof(*cmd));
2888 cmd->keyIndex = keyIndex;
2890 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
2891 NO_SYNC_WMIFLAG));
2895 wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
2896 bool set)
2898 void *osbuf;
2899 WMI_SET_PMKID_CMD *cmd;
2901 if (bssid == NULL) {
2902 return A_EINVAL;
2905 if ((set == true) && (pmkId == NULL)) {
2906 return A_EINVAL;
2909 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2910 if (osbuf == NULL) {
2911 return A_NO_MEMORY;
2914 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2916 cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
2917 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
2918 if (set == true) {
2919 memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
2920 cmd->enable = PMKID_ENABLE;
2921 } else {
2922 A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
2923 cmd->enable = PMKID_DISABLE;
2926 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
2930 wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
2932 void *osbuf;
2933 WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
2935 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2936 if (osbuf == NULL) {
2937 return A_NO_MEMORY;
2940 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2942 cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
2943 cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
2945 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
2946 NO_SYNC_WMIFLAG));
2950 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
2951 WMI_SET_AKMP_PARAMS_CMD *akmpParams)
2953 void *osbuf;
2954 WMI_SET_AKMP_PARAMS_CMD *cmd;
2956 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2957 if (osbuf == NULL) {
2958 return A_NO_MEMORY;
2961 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2962 cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2963 cmd->akmpInfo = akmpParams->akmpInfo;
2965 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
2966 NO_SYNC_WMIFLAG));
2970 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
2971 WMI_SET_PMKID_LIST_CMD *pmkInfo)
2973 void *osbuf;
2974 WMI_SET_PMKID_LIST_CMD *cmd;
2975 u16 cmdLen;
2976 u8 i;
2978 cmdLen = sizeof(pmkInfo->numPMKID) +
2979 pmkInfo->numPMKID * sizeof(WMI_PMKID);
2981 osbuf = A_NETBUF_ALLOC(cmdLen);
2982 if (osbuf == NULL) {
2983 return A_NO_MEMORY;
2986 A_NETBUF_PUT(osbuf, cmdLen);
2987 cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2988 cmd->numPMKID = pmkInfo->numPMKID;
2990 for (i = 0; i < cmd->numPMKID; i++) {
2991 memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
2992 WMI_PMKID_LEN);
2995 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
2996 NO_SYNC_WMIFLAG));
3000 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
3002 return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
3006 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
3008 WMI_DATA_HDR *dtHdr;
3010 A_ASSERT( eid != wmip->wmi_endpoint_id);
3011 A_ASSERT(osbuf != NULL);
3013 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
3014 return A_NO_MEMORY;
3017 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
3018 dtHdr->info =
3019 (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
3021 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid));
3023 return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid));
3026 typedef struct _WMI_DATA_SYNC_BUFS {
3027 u8 trafficClass;
3028 void *osbuf;
3029 }WMI_DATA_SYNC_BUFS;
3031 static int
3032 wmi_sync_point(struct wmi_t *wmip)
3034 void *cmd_osbuf;
3035 WMI_SYNC_CMD *cmd;
3036 WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
3037 u8 i,numPriStreams=0;
3038 int status = 0;
3040 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3042 memset(dataSyncBufs,0,sizeof(dataSyncBufs));
3044 /* lock out while we walk through the priority list and assemble our local array */
3045 LOCK_WMI(wmip);
3047 for (i=0; i < WMM_NUM_AC ; i++) {
3048 if (wmip->wmi_fatPipeExists & (1 << i)) {
3049 numPriStreams++;
3050 dataSyncBufs[numPriStreams-1].trafficClass = i;
3054 UNLOCK_WMI(wmip);
3056 /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
3058 do {
3060 * We allocate all network buffers needed so we will be able to
3061 * send all required frames.
3063 cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3064 if (cmd_osbuf == NULL) {
3065 status = A_NO_MEMORY;
3066 break;
3069 A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd));
3071 cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf));
3072 A_MEMZERO(cmd, sizeof(*cmd));
3074 /* In the SYNC cmd sent on the control Ep, send a bitmap of the data
3075 * eps on which the Data Sync will be sent
3077 cmd->dataSyncMap = wmip->wmi_fatPipeExists;
3079 for (i=0; i < numPriStreams ; i++) {
3080 dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
3081 if (dataSyncBufs[i].osbuf == NULL) {
3082 status = A_NO_MEMORY;
3083 break;
3085 } //end for
3087 /* if Buffer allocation for any of the dataSync fails, then do not
3088 * send the Synchronize cmd on the control ep
3090 if (status) {
3091 break;
3095 * Send sync cmd followed by sync data messages on all endpoints being
3096 * used
3098 status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
3099 NO_SYNC_WMIFLAG);
3101 if (status) {
3102 break;
3104 /* cmd buffer sent, we no longer own it */
3105 cmd_osbuf = NULL;
3107 for(i=0; i < numPriStreams; i++) {
3108 A_ASSERT(dataSyncBufs[i].osbuf != NULL);
3109 status = wmi_dataSync_send(wmip,
3110 dataSyncBufs[i].osbuf,
3111 A_WMI_Ac2EndpointID(wmip->wmi_devt,
3112 dataSyncBufs[i].
3113 trafficClass)
3116 if (status) {
3117 break;
3119 /* we don't own this buffer anymore, NULL it out of the array so it
3120 * won't get cleaned up */
3121 dataSyncBufs[i].osbuf = NULL;
3122 } //end for
3124 } while(false);
3126 /* free up any resources left over (possibly due to an error) */
3128 if (cmd_osbuf != NULL) {
3129 A_NETBUF_FREE(cmd_osbuf);
3132 for (i = 0; i < numPriStreams; i++) {
3133 if (dataSyncBufs[i].osbuf != NULL) {
3134 A_NETBUF_FREE(dataSyncBufs[i].osbuf);
3138 return (status);
3142 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
3144 void *osbuf;
3145 WMI_CREATE_PSTREAM_CMD *cmd;
3146 u8 fatPipeExistsForAC=0;
3147 s32 minimalPHY = 0;
3148 s32 nominalPHY = 0;
3150 /* Validate all the parameters. */
3151 if( !((params->userPriority < 8) &&
3152 (params->userPriority <= 0x7) &&
3153 (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
3154 (params->trafficDirection == UPLINK_TRAFFIC ||
3155 params->trafficDirection == DNLINK_TRAFFIC ||
3156 params->trafficDirection == BIDIR_TRAFFIC) &&
3157 (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
3158 params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
3159 (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
3160 params->voicePSCapability == ENABLE_FOR_THIS_AC ||
3161 params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
3162 (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
3164 return A_EINVAL;
3168 // check nominal PHY rate is >= minimalPHY, so that DUT
3169 // can allow TSRS IE
3172 // get the physical rate
3173 minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps
3175 // check minimal phy < nominal phy rate
3177 if (params->nominalPHY >= minimalPHY)
3179 nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps
3180 A_DPRINTF(DBG_WMI,
3181 (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG,
3182 minimalPHY, nominalPHY));
3184 params->nominalPHY = nominalPHY;
3186 else
3188 params->nominalPHY = 0;
3191 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3192 if (osbuf == NULL) {
3193 return A_NO_MEMORY;
3196 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3198 A_DPRINTF(DBG_WMI,
3199 (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
3200 params->trafficClass, params->tsid));
3202 cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3203 A_MEMZERO(cmd, sizeof(*cmd));
3204 memcpy(cmd, params, sizeof(*cmd));
3206 /* this is an implicitly created Fat pipe */
3207 if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
3208 LOCK_WMI(wmip);
3209 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3210 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3211 UNLOCK_WMI(wmip);
3212 } else {
3213 /* this is an explicitly created thin stream within a fat pipe */
3214 LOCK_WMI(wmip);
3215 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3216 wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
3217 /* if a thinstream becomes active, the fat pipe automatically
3218 * becomes active
3220 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3221 UNLOCK_WMI(wmip);
3224 /* Indicate activty change to driver layer only if this is the
3225 * first TSID to get created in this AC explicitly or an implicit
3226 * fat pipe is getting created.
3228 if (!fatPipeExistsForAC) {
3229 A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
3232 /* mike: should be SYNC_BEFORE_WMIFLAG */
3233 return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
3234 NO_SYNC_WMIFLAG));
3238 wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
3240 void *osbuf;
3241 WMI_DELETE_PSTREAM_CMD *cmd;
3242 int status;
3243 u16 activeTsids=0;
3245 /* validate the parameters */
3246 if (trafficClass > 3) {
3247 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass));
3248 return A_EINVAL;
3251 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3252 if (osbuf == NULL) {
3253 return A_NO_MEMORY;
3256 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3258 cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3259 A_MEMZERO(cmd, sizeof(*cmd));
3261 cmd->trafficClass = trafficClass;
3262 cmd->tsid = tsid;
3264 LOCK_WMI(wmip);
3265 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3266 UNLOCK_WMI(wmip);
3268 /* Check if the tsid was created & exists */
3269 if (!(activeTsids & (1<<tsid))) {
3271 A_NETBUF_FREE(osbuf);
3272 A_DPRINTF(DBG_WMI,
3273 (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
3274 /* TODO: return a more appropriate err code */
3275 return A_ERROR;
3278 A_DPRINTF(DBG_WMI,
3279 (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
3281 status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
3282 SYNC_BEFORE_WMIFLAG));
3284 LOCK_WMI(wmip);
3285 wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
3286 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3287 UNLOCK_WMI(wmip);
3290 /* Indicate stream inactivity to driver layer only if all tsids
3291 * within this AC are deleted.
3293 if(!activeTsids) {
3294 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
3295 wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
3298 return status;
3302 wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
3304 void *osbuf;
3305 WMI_FRAME_RATES_CMD *cmd;
3306 u8 frameType;
3308 A_DPRINTF(DBG_WMI,
3309 (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
3311 if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) ||
3312 (subType > 15)){
3314 return A_EINVAL;
3317 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3318 if (osbuf == NULL) {
3319 return A_NO_MEMORY;
3322 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3324 cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3325 A_MEMZERO(cmd, sizeof(*cmd));
3327 frameType = (u8)((subType << 4) | type);
3329 cmd->bEnableMask = bEnable;
3330 cmd->frameType = frameType;
3331 cmd->frameRateMask = rateMask;
3333 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG));
3337 * used to set the bit rate. rate is in Kbps. If rate == -1
3338 * then auto selection is used.
3341 wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
3343 void *osbuf;
3344 WMI_BIT_RATE_CMD *cmd;
3345 s8 drix, mrix, crix, ret_val;
3347 if (dataRate != -1) {
3348 ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
3349 if(ret_val == A_EINVAL){
3350 return A_EINVAL;
3352 } else {
3353 drix = -1;
3356 if (mgmtRate != -1) {
3357 ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix);
3358 if(ret_val == A_EINVAL){
3359 return A_EINVAL;
3361 } else {
3362 mrix = -1;
3364 if (ctlRate != -1) {
3365 ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix);
3366 if(ret_val == A_EINVAL){
3367 return A_EINVAL;
3369 } else {
3370 crix = -1;
3372 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3373 if (osbuf == NULL) {
3374 return A_NO_MEMORY;
3377 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3379 cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
3380 A_MEMZERO(cmd, sizeof(*cmd));
3382 cmd->rateIndex = drix;
3383 cmd->mgmtRateIndex = mrix;
3384 cmd->ctlRateIndex = crix;
3387 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
3391 wmi_get_bitrate_cmd(struct wmi_t *wmip)
3393 return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
3397 * Returns true iff the given rate index is legal in the current PHY mode.
3399 bool
3400 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
3402 WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
3403 bool isValid = true;
3404 switch(phyMode) {
3405 case WMI_11A_MODE:
3406 if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
3407 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3408 isValid = false;
3410 } else {
3411 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
3412 isValid = false;
3415 break;
3417 case WMI_11B_MODE:
3418 if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
3419 isValid = false;
3421 break;
3423 case WMI_11GONLY_MODE:
3424 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3425 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3426 isValid = false;
3428 } else {
3429 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
3430 isValid = false;
3433 break;
3435 case WMI_11G_MODE:
3436 case WMI_11AG_MODE:
3437 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3438 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3439 isValid = false;
3441 } else {
3442 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
3443 isValid = false;
3446 break;
3447 default:
3448 A_ASSERT(false);
3449 break;
3452 return isValid;
3455 s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
3457 s8 i;
3459 for (i=0;;i++)
3461 if (wmi_rateTable[(u32) i][0] == 0) {
3462 return A_EINVAL;
3464 if (wmi_rateTable[(u32) i][0] == rate) {
3465 break;
3469 if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
3470 return A_EINVAL;
3473 *rate_idx = i;
3474 return 0;
3478 wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
3480 void *osbuf;
3481 WMI_FIX_RATES_CMD *cmd;
3482 #if 0
3483 s32 rateIndex;
3484 /* This check does not work for AR6003 as the HT modes are enabled only when
3485 * the STA is connected to a HT_BSS and is not based only on channel. It is
3486 * safe to skip this check however because rate control will only use rates
3487 * that are permitted by the valid rate mask and the fix rate mask. Meaning
3488 * the fix rate mask is not sufficient by itself to cause an invalid rate
3489 * to be used. */
3490 /* Make sure all rates in the mask are valid in the current PHY mode */
3491 for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
3492 if((1 << rateIndex) & (u32)fixRatesMask) {
3493 if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
3494 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
3495 return A_EINVAL;
3499 #endif
3502 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3503 if (osbuf == NULL) {
3504 return A_NO_MEMORY;
3507 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3509 cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3510 A_MEMZERO(cmd, sizeof(*cmd));
3512 cmd->fixRateMask = fixRatesMask;
3514 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
3518 wmi_get_ratemask_cmd(struct wmi_t *wmip)
3520 return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3524 wmi_get_channelList_cmd(struct wmi_t *wmip)
3526 return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
3530 * used to generate a wmi sey channel Parameters cmd.
3531 * mode should always be specified and corresponds to the phy mode of the
3532 * wlan.
3533 * numChan should alway sbe specified. If zero indicates that all available
3534 * channels should be used.
3535 * channelList is an array of channel frequencies (in Mhz) which the radio
3536 * should limit its operation to. It should be NULL if numChan == 0. Size of
3537 * array should correspond to numChan entries.
3540 wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
3541 WMI_PHY_MODE mode, s8 numChan,
3542 u16 *channelList)
3544 void *osbuf;
3545 WMI_CHANNEL_PARAMS_CMD *cmd;
3546 s8 size;
3548 size = sizeof (*cmd);
3550 if (numChan) {
3551 if (numChan > WMI_MAX_CHANNELS) {
3552 return A_EINVAL;
3554 size += sizeof(u16) * (numChan - 1);
3557 osbuf = A_NETBUF_ALLOC(size);
3558 if (osbuf == NULL) {
3559 return A_NO_MEMORY;
3562 A_NETBUF_PUT(osbuf, size);
3564 cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3565 A_MEMZERO(cmd, size);
3567 wmip->wmi_phyMode = mode;
3568 cmd->scanParam = scanParam;
3569 cmd->phyMode = mode;
3570 cmd->numChannels = numChan;
3571 memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
3573 return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3574 NO_SYNC_WMIFLAG));
3577 void
3578 wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3580 SQ_THRESHOLD_PARAMS *sq_thresh =
3581 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
3583 * Parse the command and store the threshold values here. The checks
3584 * for valid values can be put here
3586 sq_thresh->weight = rssiCmd->weight;
3587 sq_thresh->polling_interval = rssiCmd->pollTime;
3589 sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3590 sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3591 sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3592 sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3593 sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3594 sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3595 sq_thresh->upper_threshold_valid_count = 6;
3597 /* List sorted in descending order */
3598 sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3599 sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3600 sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3601 sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3602 sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3603 sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3604 sq_thresh->lower_threshold_valid_count = 6;
3606 if (!rssi_event_value) {
3608 * Configuring the thresholds to their extremes allows the host to get an
3609 * event from the target which is used for the configuring the correct
3610 * thresholds
3612 rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
3613 rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
3614 } else {
3616 * In case the user issues multiple times of rssi_threshold_setting,
3617 * we should not use the extreames anymore, the target does not expect that.
3619 rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
3620 sq_thresh->upper_threshold_valid_count);
3621 rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
3622 sq_thresh->lower_threshold_valid_count);
3627 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
3628 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3631 /* Check these values are in ascending order */
3632 if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
3633 rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
3634 rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
3635 rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
3636 rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
3637 rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
3638 rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
3639 rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
3640 rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
3641 rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
3643 return A_EINVAL;
3646 wmi_cache_configure_rssithreshold(wmip, rssiCmd);
3648 return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
3652 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
3654 void *osbuf;
3655 WMI_SET_IP_CMD *cmd;
3657 /* Multicast address are not valid */
3658 if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3659 (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
3660 return A_EINVAL;
3663 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
3664 if (osbuf == NULL) {
3665 return A_NO_MEMORY;
3668 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
3669 cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
3670 memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
3672 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3673 NO_SYNC_WMIFLAG));
3677 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3678 WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3680 void *osbuf;
3681 s8 size;
3682 WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
3683 u16 activeTsids=0;
3684 u8 streamExists=0;
3685 u8 i;
3687 if( hostModeCmd->awake == hostModeCmd->asleep) {
3688 return A_EINVAL;
3691 size = sizeof (*cmd);
3693 osbuf = A_NETBUF_ALLOC(size);
3694 if (osbuf == NULL) {
3695 return A_NO_MEMORY;
3698 A_NETBUF_PUT(osbuf, size);
3700 cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3701 A_MEMZERO(cmd, size);
3702 memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
3704 if(hostModeCmd->asleep) {
3706 * Relinquish credits from all implicitly created pstreams since when we
3707 * go to sleep. If user created explicit thinstreams exists with in a
3708 * fatpipe leave them intact for the user to delete
3710 LOCK_WMI(wmip);
3711 streamExists = wmip->wmi_fatPipeExists;
3712 UNLOCK_WMI(wmip);
3714 for(i=0;i< WMM_NUM_AC;i++) {
3715 if (streamExists & (1<<i)) {
3716 LOCK_WMI(wmip);
3717 activeTsids = wmip->wmi_streamExistsForAC[i];
3718 UNLOCK_WMI(wmip);
3719 /* If there are no user created thin streams delete the fatpipe */
3720 if(!activeTsids) {
3721 streamExists &= ~(1<<i);
3722 /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
3723 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
3728 /* Update the fatpipes that exists*/
3729 LOCK_WMI(wmip);
3730 wmip->wmi_fatPipeExists = streamExists;
3731 UNLOCK_WMI(wmip);
3734 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
3735 NO_SYNC_WMIFLAG));
3739 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3740 WMI_SET_WOW_MODE_CMD *wowModeCmd)
3742 void *osbuf;
3743 s8 size;
3744 WMI_SET_WOW_MODE_CMD *cmd;
3746 size = sizeof (*cmd);
3748 osbuf = A_NETBUF_ALLOC(size);
3749 if (osbuf == NULL) {
3750 return A_NO_MEMORY;
3753 A_NETBUF_PUT(osbuf, size);
3755 cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3756 A_MEMZERO(cmd, size);
3757 memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
3759 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3760 NO_SYNC_WMIFLAG));
3765 wmi_get_wow_list_cmd(struct wmi_t *wmip,
3766 WMI_GET_WOW_LIST_CMD *wowListCmd)
3768 void *osbuf;
3769 s8 size;
3770 WMI_GET_WOW_LIST_CMD *cmd;
3772 size = sizeof (*cmd);
3774 osbuf = A_NETBUF_ALLOC(size);
3775 if (osbuf == NULL) {
3776 return A_NO_MEMORY;
3779 A_NETBUF_PUT(osbuf, size);
3781 cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
3782 A_MEMZERO(cmd, size);
3783 memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
3785 return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3786 NO_SYNC_WMIFLAG));
3790 static int
3791 wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
3793 WMI_GET_WOW_LIST_REPLY *reply;
3795 if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
3796 return A_EINVAL;
3798 reply = (WMI_GET_WOW_LIST_REPLY *)datap;
3800 A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
3801 reply);
3803 return 0;
3806 int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
3807 WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
3808 u8 *pattern, u8 *mask,
3809 u8 pattern_size)
3811 void *osbuf;
3812 s8 size;
3813 WMI_ADD_WOW_PATTERN_CMD *cmd;
3814 u8 *filter_mask = NULL;
3816 size = sizeof (*cmd);
3818 size += ((2 * addWowCmd->filter_size)* sizeof(u8));
3819 osbuf = A_NETBUF_ALLOC(size);
3820 if (osbuf == NULL) {
3821 return A_NO_MEMORY;
3824 A_NETBUF_PUT(osbuf, size);
3826 cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3827 cmd->filter_list_id = addWowCmd->filter_list_id;
3828 cmd->filter_offset = addWowCmd->filter_offset;
3829 cmd->filter_size = addWowCmd->filter_size;
3831 memcpy(cmd->filter, pattern, addWowCmd->filter_size);
3833 filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
3834 memcpy(filter_mask, mask, addWowCmd->filter_size);
3837 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3838 NO_SYNC_WMIFLAG));
3842 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3843 WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3845 void *osbuf;
3846 s8 size;
3847 WMI_DEL_WOW_PATTERN_CMD *cmd;
3849 size = sizeof (*cmd);
3851 osbuf = A_NETBUF_ALLOC(size);
3852 if (osbuf == NULL) {
3853 return A_NO_MEMORY;
3856 A_NETBUF_PUT(osbuf, size);
3858 cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3859 A_MEMZERO(cmd, size);
3860 memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
3862 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3863 NO_SYNC_WMIFLAG));
3867 void
3868 wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3870 SQ_THRESHOLD_PARAMS *sq_thresh =
3871 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
3873 * Parse the command and store the threshold values here. The checks
3874 * for valid values can be put here
3876 sq_thresh->weight = snrCmd->weight;
3877 sq_thresh->polling_interval = snrCmd->pollTime;
3879 sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
3880 sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
3881 sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
3882 sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
3883 sq_thresh->upper_threshold_valid_count = 4;
3885 /* List sorted in descending order */
3886 sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
3887 sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
3888 sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
3889 sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
3890 sq_thresh->lower_threshold_valid_count = 4;
3892 if (!snr_event_value) {
3894 * Configuring the thresholds to their extremes allows the host to get an
3895 * event from the target which is used for the configuring the correct
3896 * thresholds
3898 snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3899 snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
3900 } else {
3902 * In case the user issues multiple times of snr_threshold_setting,
3903 * we should not use the extreames anymore, the target does not expect that.
3905 snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
3906 sq_thresh->upper_threshold_valid_count);
3907 snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
3908 sq_thresh->lower_threshold_valid_count);
3913 wmi_set_snr_threshold_params(struct wmi_t *wmip,
3914 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3916 if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
3917 snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
3918 snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
3919 snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
3920 snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
3921 snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
3923 return A_EINVAL;
3925 wmi_cache_configure_snrthreshold(wmip, snrCmd);
3926 return (wmi_send_snr_threshold_params(wmip, snrCmd));
3930 wmi_clr_rssi_snr(struct wmi_t *wmip)
3932 void *osbuf;
3934 osbuf = A_NETBUF_ALLOC(sizeof(int));
3935 if (osbuf == NULL) {
3936 return A_NO_MEMORY;
3939 return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
3940 NO_SYNC_WMIFLAG));
3944 wmi_set_lq_threshold_params(struct wmi_t *wmip,
3945 WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
3947 void *osbuf;
3948 s8 size;
3949 WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
3950 /* These values are in ascending order */
3951 if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
3952 lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
3953 lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
3954 lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
3955 lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
3956 lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
3958 return A_EINVAL;
3961 size = sizeof (*cmd);
3963 osbuf = A_NETBUF_ALLOC(size);
3964 if (osbuf == NULL) {
3965 return A_NO_MEMORY;
3968 A_NETBUF_PUT(osbuf, size);
3970 cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3971 A_MEMZERO(cmd, size);
3972 memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
3974 return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
3975 NO_SYNC_WMIFLAG));
3979 wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
3981 void *osbuf;
3982 s8 size;
3983 WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
3985 size = sizeof (*cmd);
3987 osbuf = A_NETBUF_ALLOC(size);
3988 if (osbuf == NULL) {
3989 return A_NO_MEMORY;
3992 A_NETBUF_PUT(osbuf, size);
3994 cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
3995 A_MEMZERO(cmd, size);
3997 cmd->bitmask = mask;
3999 return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
4000 NO_SYNC_WMIFLAG));
4004 wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
4006 void *osbuf;
4007 WMIX_HB_CHALLENGE_RESP_CMD *cmd;
4009 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4010 if (osbuf == NULL) {
4011 return A_NO_MEMORY;
4014 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4016 cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
4017 cmd->cookie = cookie;
4018 cmd->source = source;
4020 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
4021 NO_SYNC_WMIFLAG));
4025 wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
4026 u16 tsr, bool rep, u16 size,
4027 u32 valid)
4029 void *osbuf;
4030 WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
4032 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4033 if (osbuf == NULL) {
4034 return A_NO_MEMORY;
4037 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4039 cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
4040 cmd->config.cfgmmask = mmask;
4041 cmd->config.cfgtsr = tsr;
4042 cmd->config.cfgrep = rep;
4043 cmd->config.cfgsize = size;
4044 cmd->config.cfgvalid = valid;
4046 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
4047 NO_SYNC_WMIFLAG));
4051 wmi_get_stats_cmd(struct wmi_t *wmip)
4053 return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4057 wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
4059 void *osbuf;
4060 WMI_ADD_BAD_AP_CMD *cmd;
4062 if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
4063 return A_EINVAL;
4066 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4067 if (osbuf == NULL) {
4068 return A_NO_MEMORY;
4071 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4073 cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4074 cmd->badApIndex = apIndex;
4075 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4077 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4081 wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
4083 void *osbuf;
4084 WMI_DELETE_BAD_AP_CMD *cmd;
4086 if (apIndex > WMI_MAX_BAD_AP_INDEX) {
4087 return A_EINVAL;
4090 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4091 if (osbuf == NULL) {
4092 return A_NO_MEMORY;
4095 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4097 cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4098 cmd->badApIndex = apIndex;
4100 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
4101 NO_SYNC_WMIFLAG));
4105 wmi_abort_scan_cmd(struct wmi_t *wmip)
4107 return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4111 wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
4113 void *osbuf;
4114 WMI_SET_TX_PWR_CMD *cmd;
4116 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4117 if (osbuf == NULL) {
4118 return A_NO_MEMORY;
4121 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4123 cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
4124 cmd->dbM = dbM;
4126 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
4130 wmi_get_txPwr_cmd(struct wmi_t *wmip)
4132 return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4135 u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
4137 u16 activeTsids=0;
4139 LOCK_WMI(wmip);
4140 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4141 UNLOCK_WMI(wmip);
4143 return activeTsids;
4147 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4149 return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4153 wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
4155 void *osbuf;
4156 u32 size = sizeof(u8);
4157 WMI_TARGET_ROAM_DATA *cmd;
4159 osbuf = A_NETBUF_ALLOC(size); /* no payload */
4160 if (osbuf == NULL) {
4161 return A_NO_MEMORY;
4164 A_NETBUF_PUT(osbuf, size);
4166 cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
4167 cmd->roamDataType = roamDataType;
4169 return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
4170 NO_SYNC_WMIFLAG));
4174 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
4175 u8 size)
4177 void *osbuf;
4178 WMI_SET_ROAM_CTRL_CMD *cmd;
4180 osbuf = A_NETBUF_ALLOC(size);
4181 if (osbuf == NULL) {
4182 return A_NO_MEMORY;
4185 A_NETBUF_PUT(osbuf, size);
4187 cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
4188 A_MEMZERO(cmd, size);
4190 memcpy(cmd, p, size);
4192 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4193 NO_SYNC_WMIFLAG));
4197 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4198 WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
4199 u8 size)
4201 void *osbuf;
4202 WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
4204 /* These timers can't be zero */
4205 if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
4206 !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
4207 pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
4208 !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
4209 pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
4210 return A_EINVAL;
4212 osbuf = A_NETBUF_ALLOC(size);
4213 if (osbuf == NULL) {
4214 return A_NO_MEMORY;
4217 A_NETBUF_PUT(osbuf, size);
4219 cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
4220 A_MEMZERO(cmd, size);
4222 memcpy(cmd, pCmd, size);
4224 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
4225 NO_SYNC_WMIFLAG));
4229 wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin,
4230 u8 eCWmax, u8 aifsn)
4232 void *osbuf;
4233 WMI_SET_ACCESS_PARAMS_CMD *cmd;
4235 if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
4236 (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
4238 return A_EINVAL;
4241 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4242 if (osbuf == NULL) {
4243 return A_NO_MEMORY;
4246 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4248 cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4249 cmd->txop = txop;
4250 cmd->eCWmin = eCWmin;
4251 cmd->eCWmax = eCWmax;
4252 cmd->aifsn = aifsn;
4253 cmd->ac = ac;
4255 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
4256 NO_SYNC_WMIFLAG));
4260 wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4261 u8 trafficClass, u8 maxRetries,
4262 u8 enableNotify)
4264 void *osbuf;
4265 WMI_SET_RETRY_LIMITS_CMD *cmd;
4267 if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
4268 (frameType != DATA_FRAMETYPE))
4270 return A_EINVAL;
4273 if (maxRetries > WMI_MAX_RETRIES) {
4274 return A_EINVAL;
4277 if (frameType != DATA_FRAMETYPE) {
4278 trafficClass = 0;
4281 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4282 if (osbuf == NULL) {
4283 return A_NO_MEMORY;
4286 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4288 cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
4289 cmd->frameType = frameType;
4290 cmd->trafficClass = trafficClass;
4291 cmd->maxRetries = maxRetries;
4292 cmd->enableNotify = enableNotify;
4294 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
4295 NO_SYNC_WMIFLAG));
4298 void
4299 wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
4301 if (bssid != NULL) {
4302 memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
4307 wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
4309 void *osbuf;
4310 WMI_SET_OPT_MODE_CMD *cmd;
4312 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4313 if (osbuf == NULL) {
4314 return A_NO_MEMORY;
4317 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4319 cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4320 A_MEMZERO(cmd, sizeof(*cmd));
4321 cmd->optMode = optMode;
4323 return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
4324 SYNC_BOTH_WMIFLAG));
4328 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
4329 u8 frmType,
4330 u8 *dstMacAddr,
4331 u8 *bssid,
4332 u16 optIEDataLen,
4333 u8 *optIEData)
4335 void *osbuf;
4336 WMI_OPT_TX_FRAME_CMD *cmd;
4337 osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
4338 if (osbuf == NULL) {
4339 return A_NO_MEMORY;
4342 A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
4344 cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
4345 A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
4347 cmd->frmType = frmType;
4348 cmd->optIEDataLen = optIEDataLen;
4349 //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd));
4350 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4351 memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4352 memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
4354 return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4355 NO_SYNC_WMIFLAG));
4359 wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
4361 void *osbuf;
4362 WMI_BEACON_INT_CMD *cmd;
4364 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4365 if (osbuf == NULL) {
4366 return A_NO_MEMORY;
4369 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4371 cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
4372 A_MEMZERO(cmd, sizeof(*cmd));
4373 cmd->beaconInterval = intvl;
4375 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
4376 NO_SYNC_WMIFLAG));
4381 wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
4383 void *osbuf;
4384 WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
4386 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4387 if (osbuf == NULL) {
4388 return A_NO_MEMORY;
4391 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4393 cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
4394 A_MEMZERO(cmd, sizeof(*cmd));
4395 cmd->voicePktSize = voicePktSize;
4397 return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
4398 NO_SYNC_WMIFLAG));
4403 wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
4405 void *osbuf;
4406 WMI_SET_MAX_SP_LEN_CMD *cmd;
4408 /* maxSPLen is a two-bit value. If user trys to set anything
4409 * other than this, then its invalid
4411 if(maxSPLen & ~0x03)
4412 return A_EINVAL;
4414 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4415 if (osbuf == NULL) {
4416 return A_NO_MEMORY;
4419 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4421 cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
4422 A_MEMZERO(cmd, sizeof(*cmd));
4423 cmd->maxSPLen = maxSPLen;
4425 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
4426 NO_SYNC_WMIFLAG));
4429 u8 wmi_determine_userPriority(
4430 u8 *pkt,
4431 u32 layer2Pri)
4433 u8 ipPri;
4434 iphdr *ipHdr = (iphdr *)pkt;
4436 /* Determine IPTOS priority */
4438 * IP Tos format :
4439 * (Refer Pg 57 WMM-test-plan-v1.2)
4440 * IP-TOS - 8bits
4441 * : DSCP(6-bits) ECN(2-bits)
4442 * : DSCP - P2 P1 P0 X X X
4443 * where (P2 P1 P0) form 802.1D
4445 ipPri = ipHdr->ip_tos >> 5;
4446 ipPri &= 0x7;
4448 if ((layer2Pri & 0x7) > ipPri)
4449 return ((u8)layer2Pri & 0x7);
4450 else
4451 return ipPri;
4454 u8 convert_userPriority_to_trafficClass(u8 userPriority)
4456 return (up_to_ac[userPriority & 0x7]);
4459 u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
4461 return wmip->wmi_powerMode;
4465 wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
4467 int ret = 0;
4469 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
4470 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0
4471 #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0
4472 #define TSPEC_DELAY_BOUND_ATHEROS_DEF 0
4473 #define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0
4474 #define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */
4476 /* Verify TSPEC params for ATHEROS compliance */
4477 if(tspecCompliance == ATHEROS_COMPLIANCE) {
4478 if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
4479 (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
4480 (pCmd->minDataRate != pCmd->meanDataRate) ||
4481 (pCmd->minDataRate != pCmd->peakDataRate) ||
4482 (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
4483 (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
4484 (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
4485 (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
4487 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
4488 //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
4489 ret = A_EINVAL;
4493 return ret;
4496 #ifdef CONFIG_HOST_TCMD_SUPPORT
4497 static int
4498 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
4501 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4503 return 0;
4506 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
4509 wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
4511 void *osbuf;
4512 WMI_SET_AUTH_MODE_CMD *cmd;
4514 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4515 if (osbuf == NULL) {
4516 return A_NO_MEMORY;
4519 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4521 cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4522 A_MEMZERO(cmd, sizeof(*cmd));
4523 cmd->mode = mode;
4525 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
4526 NO_SYNC_WMIFLAG));
4530 wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
4532 void *osbuf;
4533 WMI_SET_REASSOC_MODE_CMD *cmd;
4535 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4536 if (osbuf == NULL) {
4537 return A_NO_MEMORY;
4540 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4542 cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4543 A_MEMZERO(cmd, sizeof(*cmd));
4544 cmd->mode = mode;
4546 return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
4547 NO_SYNC_WMIFLAG));
4551 wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
4553 void *osbuf;
4554 WMI_SET_LPREAMBLE_CMD *cmd;
4556 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4557 if (osbuf == NULL) {
4558 return A_NO_MEMORY;
4561 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4563 cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
4564 A_MEMZERO(cmd, sizeof(*cmd));
4565 cmd->status = status;
4566 cmd->preamblePolicy = preamblePolicy;
4568 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
4569 NO_SYNC_WMIFLAG));
4573 wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
4575 void *osbuf;
4576 WMI_SET_RTS_CMD *cmd;
4578 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4579 if (osbuf == NULL) {
4580 return A_NO_MEMORY;
4583 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4585 cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
4586 A_MEMZERO(cmd, sizeof(*cmd));
4587 cmd->threshold = threshold;
4589 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
4590 NO_SYNC_WMIFLAG));
4594 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
4596 void *osbuf;
4597 WMI_SET_WMM_CMD *cmd;
4599 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4600 if (osbuf == NULL) {
4601 return A_NO_MEMORY;
4604 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4606 cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
4607 A_MEMZERO(cmd, sizeof(*cmd));
4608 cmd->status = status;
4610 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
4611 NO_SYNC_WMIFLAG));
4616 wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
4618 void *osbuf;
4619 WMI_SET_QOS_SUPP_CMD *cmd;
4621 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4622 if (osbuf == NULL) {
4623 return A_NO_MEMORY;
4626 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4628 cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
4629 A_MEMZERO(cmd, sizeof(*cmd));
4630 cmd->status = status;
4631 return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
4632 NO_SYNC_WMIFLAG));
4637 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
4639 void *osbuf;
4640 WMI_SET_WMM_TXOP_CMD *cmd;
4642 if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
4643 return A_EINVAL;
4645 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4646 if (osbuf == NULL) {
4647 return A_NO_MEMORY;
4650 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4652 cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
4653 A_MEMZERO(cmd, sizeof(*cmd));
4654 cmd->txopEnable = cfg;
4656 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
4657 NO_SYNC_WMIFLAG));
4662 wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
4664 void *osbuf;
4665 WMI_AP_SET_COUNTRY_CMD *cmd;
4667 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4668 if (osbuf == NULL) {
4669 return A_NO_MEMORY;
4672 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4674 cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
4675 A_MEMZERO(cmd, sizeof(*cmd));
4676 memcpy(cmd->countryCode,countryCode,3);
4678 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
4679 NO_SYNC_WMIFLAG));
4682 #ifdef CONFIG_HOST_TCMD_SUPPORT
4683 /* WMI layer doesn't need to know the data type of the test cmd.
4684 This would be beneficial for customers like Qualcomm, who might
4685 have different test command requirements from differnt manufacturers
4688 wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
4690 void *osbuf;
4691 char *data;
4693 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4695 osbuf= A_NETBUF_ALLOC(len);
4696 if(osbuf == NULL)
4698 return A_NO_MEMORY;
4700 A_NETBUF_PUT(osbuf, len);
4701 data = A_NETBUF_DATA(osbuf);
4702 memcpy(data, buf, len);
4704 return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4705 NO_SYNC_WMIFLAG));
4708 #endif
4711 wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
4713 void *osbuf;
4714 WMI_SET_BT_STATUS_CMD *cmd;
4716 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
4718 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4719 if (osbuf == NULL) {
4720 return A_NO_MEMORY;
4723 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4725 cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4726 A_MEMZERO(cmd, sizeof(*cmd));
4727 cmd->streamType = streamType;
4728 cmd->status = status;
4730 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
4731 NO_SYNC_WMIFLAG));
4735 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
4737 void *osbuf;
4738 WMI_SET_BT_PARAMS_CMD* alloc_cmd;
4740 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
4742 if (cmd->paramType == BT_PARAM_SCO) {
4743 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,
4744 cmd->info.scoParams.dataResponseTimeout,
4745 cmd->info.scoParams.stompScoRules,
4746 cmd->info.scoParams.scoOptFlags,
4747 cmd->info.scoParams.stompDutyCyleVal,
4748 cmd->info.scoParams.stompDutyCyleMaxVal,
4749 cmd->info.scoParams.psPollLatencyFraction,
4750 cmd->info.scoParams.noSCOSlots,
4751 cmd->info.scoParams.noIdleSlots,
4752 cmd->info.scoParams.scoOptOffRssi,
4753 cmd->info.scoParams.scoOptOnRssi,
4754 cmd->info.scoParams.scoOptRtsCount));
4756 else if (cmd->paramType == BT_PARAM_A2DP) {
4757 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
4758 cmd->info.a2dpParams.a2dpBurstCntMin,
4759 cmd->info.a2dpParams.a2dpDataRespTimeout,
4760 cmd->info.a2dpParams.a2dpOptFlags,
4761 cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
4762 cmd->info.a2dpParams.a2dpOptOffRssi,
4763 cmd->info.a2dpParams.a2dpOptOnRssi,
4764 cmd->info.a2dpParams.a2dpOptRtsCount));
4766 else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
4767 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
4769 else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
4770 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
4772 else if (cmd->paramType == BT_PARAM_ACLCOEX) {
4773 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
4774 cmd->info.aclCoexParams.aclBtMediumUsageTime,
4775 cmd->info.aclCoexParams.aclDataRespTimeout));
4777 else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
4778 A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
4781 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4782 if (osbuf == NULL) {
4783 return A_NO_MEMORY;
4786 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4788 alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4789 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4790 memcpy(alloc_cmd, cmd, sizeof(*cmd));
4792 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4793 NO_SYNC_WMIFLAG));
4797 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
4799 void *osbuf;
4800 WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
4802 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4803 if (osbuf == NULL) {
4804 return A_NO_MEMORY;
4806 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4807 alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
4808 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4809 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
4810 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4811 NO_SYNC_WMIFLAG));
4817 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
4818 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
4820 void *osbuf;
4821 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
4823 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4824 if (osbuf == NULL) {
4825 return A_NO_MEMORY;
4827 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4828 alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
4829 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4830 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
4831 A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
4832 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
4833 NO_SYNC_WMIFLAG));
4838 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
4839 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
4841 void *osbuf;
4842 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
4844 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4845 if (osbuf == NULL) {
4846 return A_NO_MEMORY;
4848 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4849 alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4850 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4851 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
4852 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
4853 NO_SYNC_WMIFLAG));
4858 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
4859 WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
4861 void *osbuf;
4862 WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
4864 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4865 if (osbuf == NULL) {
4866 return A_NO_MEMORY;
4868 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4869 alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4870 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4871 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
4872 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
4873 NO_SYNC_WMIFLAG));
4878 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
4879 WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
4881 void *osbuf;
4882 WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
4884 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4885 if (osbuf == NULL) {
4886 return A_NO_MEMORY;
4888 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4889 alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4890 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4891 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
4892 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
4893 NO_SYNC_WMIFLAG));
4898 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
4899 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
4901 void *osbuf;
4902 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
4904 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4905 if (osbuf == NULL) {
4906 return A_NO_MEMORY;
4908 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4909 alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4910 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4911 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
4912 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
4913 NO_SYNC_WMIFLAG));
4918 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
4920 void *osbuf;
4921 WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
4923 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4924 if (osbuf == NULL) {
4925 return A_NO_MEMORY;
4927 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4928 alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
4929 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4930 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
4931 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
4932 NO_SYNC_WMIFLAG));
4937 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
4938 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
4940 void *osbuf;
4941 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
4943 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4944 if (osbuf == NULL) {
4945 return A_NO_MEMORY;
4947 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4948 alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4949 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4950 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
4951 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
4952 NO_SYNC_WMIFLAG));
4957 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
4959 void *osbuf;
4960 WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
4962 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4963 if (osbuf == NULL) {
4964 return A_NO_MEMORY;
4966 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4967 alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4968 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4969 memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
4970 return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
4971 NO_SYNC_WMIFLAG));
4976 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
4979 return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
4984 wmi_get_keepalive_configured(struct wmi_t *wmip)
4986 void *osbuf;
4987 WMI_GET_KEEPALIVE_CMD *cmd;
4988 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4989 if (osbuf == NULL) {
4990 return A_NO_MEMORY;
4992 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4993 cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4994 A_MEMZERO(cmd, sizeof(*cmd));
4995 return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
4996 NO_SYNC_WMIFLAG));
4999 u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
5001 return wmip->wmi_keepaliveInterval;
5005 wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
5007 void *osbuf;
5008 WMI_SET_KEEPALIVE_CMD *cmd;
5010 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5011 if (osbuf == NULL) {
5012 return A_NO_MEMORY;
5015 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5017 cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
5018 A_MEMZERO(cmd, sizeof(*cmd));
5019 cmd->keepaliveInterval = keepaliveInterval;
5020 wmip->wmi_keepaliveInterval = keepaliveInterval;
5022 return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
5023 NO_SYNC_WMIFLAG));
5027 wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
5029 void *osbuf;
5030 WMI_SET_PARAMS_CMD *cmd;
5032 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
5033 if (osbuf == NULL) {
5034 return A_NO_MEMORY;
5037 A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
5039 cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5040 A_MEMZERO(cmd, sizeof(*cmd));
5041 cmd->opcode = opcode;
5042 cmd->length = length;
5043 memcpy(cmd->buffer, buffer, length);
5045 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5046 NO_SYNC_WMIFLAG));
5051 wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5053 void *osbuf;
5054 WMI_SET_MCAST_FILTER_CMD *cmd;
5056 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5057 if (osbuf == NULL) {
5058 return A_NO_MEMORY;
5061 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5063 cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5064 cmd->multicast_mac[0] = 0x01;
5065 cmd->multicast_mac[1] = 0x00;
5066 cmd->multicast_mac[2] = 0x5e;
5067 cmd->multicast_mac[3] = dot2&0x7F;
5068 cmd->multicast_mac[4] = dot3;
5069 cmd->multicast_mac[5] = dot4;
5071 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
5072 NO_SYNC_WMIFLAG));
5077 wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5079 void *osbuf;
5080 WMI_SET_MCAST_FILTER_CMD *cmd;
5082 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5083 if (osbuf == NULL) {
5084 return A_NO_MEMORY;
5087 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5089 cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5090 cmd->multicast_mac[0] = 0x01;
5091 cmd->multicast_mac[1] = 0x00;
5092 cmd->multicast_mac[2] = 0x5e;
5093 cmd->multicast_mac[3] = dot2&0x7F;
5094 cmd->multicast_mac[4] = dot3;
5095 cmd->multicast_mac[5] = dot4;
5097 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID,
5098 NO_SYNC_WMIFLAG));
5102 wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
5104 void *osbuf;
5105 WMI_MCAST_FILTER_CMD *cmd;
5107 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5108 if (osbuf == NULL) {
5109 return A_NO_MEMORY;
5112 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5114 cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5115 cmd->enable = enable;
5117 return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
5118 NO_SYNC_WMIFLAG));
5122 wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5123 u8 *ieInfo)
5125 void *osbuf;
5126 WMI_SET_APPIE_CMD *cmd;
5127 u16 cmdLen;
5129 cmdLen = sizeof(*cmd) + ieLen - 1;
5130 osbuf = A_NETBUF_ALLOC(cmdLen);
5131 if (osbuf == NULL) {
5132 return A_NO_MEMORY;
5135 A_NETBUF_PUT(osbuf, cmdLen);
5137 cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
5138 A_MEMZERO(cmd, cmdLen);
5140 cmd->mgmtFrmType = mgmtFrmType;
5141 cmd->ieLen = ieLen;
5142 memcpy(cmd->ieInfo, ieInfo, ieLen);
5144 return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5148 wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
5150 void *osbuf;
5151 u8 *data;
5153 osbuf = A_NETBUF_ALLOC(dataLen);
5154 if (osbuf == NULL) {
5155 return A_NO_MEMORY;
5158 A_NETBUF_PUT(osbuf, dataLen);
5160 data = A_NETBUF_DATA(osbuf);
5162 memcpy(data, cmd, dataLen);
5164 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5167 s32 wmi_get_rate(s8 rateindex)
5169 if (rateindex == RATE_AUTO) {
5170 return 0;
5171 } else {
5172 return(wmi_rateTable[(u32) rateindex][0]);
5176 void
5177 wmi_node_return (struct wmi_t *wmip, bss_t *bss)
5179 if (NULL != bss)
5181 wlan_node_return (&wmip->wmi_scan_table, bss);
5185 void
5186 wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
5188 wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5191 bss_t *
5192 wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
5193 u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
5195 bss_t *node = NULL;
5196 node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
5197 ssidLength, bIsWPA2, bMatchSSID);
5198 return node;
5202 #ifdef THREAD_X
5203 void
5204 wmi_refresh_scan_table (struct wmi_t *wmip)
5206 wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5208 #endif
5210 void
5211 wmi_free_allnodes(struct wmi_t *wmip)
5213 wlan_free_allnodes(&wmip->wmi_scan_table);
5216 bss_t *
5217 wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
5219 bss_t *ni=NULL;
5220 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5221 return ni;
5224 void
5225 wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
5227 bss_t *ni=NULL;
5229 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5230 if (ni != NULL) {
5231 wlan_node_reclaim(&wmip->wmi_scan_table, ni);
5234 return;
5238 wmi_dset_open_reply(struct wmi_t *wmip,
5239 u32 status,
5240 u32 access_cookie,
5241 u32 dset_size,
5242 u32 dset_version,
5243 u32 targ_handle,
5244 u32 targ_reply_fn,
5245 u32 targ_reply_arg)
5247 void *osbuf;
5248 WMIX_DSETOPEN_REPLY_CMD *open_reply;
5250 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
5252 osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
5253 if (osbuf == NULL) {
5254 return A_NO_MEMORY;
5257 A_NETBUF_PUT(osbuf, sizeof(*open_reply));
5258 open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5260 open_reply->status = status;
5261 open_reply->targ_dset_handle = targ_handle;
5262 open_reply->targ_reply_fn = targ_reply_fn;
5263 open_reply->targ_reply_arg = targ_reply_arg;
5264 open_reply->access_cookie = access_cookie;
5265 open_reply->size = dset_size;
5266 open_reply->version = dset_version;
5268 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
5269 NO_SYNC_WMIFLAG));
5272 static int
5273 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5275 WMI_PMKID_LIST_REPLY *reply;
5276 u32 expected_len;
5278 if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
5279 return A_EINVAL;
5281 reply = (WMI_PMKID_LIST_REPLY *)datap;
5282 expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
5284 if (len < expected_len) {
5285 return A_EINVAL;
5288 A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
5289 reply->pmkidList, reply->bssidList[0]);
5291 return 0;
5295 static int
5296 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5298 WMI_SET_PARAMS_REPLY *reply;
5300 if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
5301 return A_EINVAL;
5303 reply = (WMI_SET_PARAMS_REPLY *)datap;
5305 if (0 == reply->status)
5309 else
5314 return 0;
5319 static int
5320 wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5322 WMI_ACM_REJECT_EVENT *ev;
5324 ev = (WMI_ACM_REJECT_EVENT *)datap;
5325 wmip->wmi_traffic_class = ev->trafficClass;
5326 printk("ACM REJECT %d\n",wmip->wmi_traffic_class);
5327 return 0;
5331 #ifdef CONFIG_HOST_DSET_SUPPORT
5333 wmi_dset_data_reply(struct wmi_t *wmip,
5334 u32 status,
5335 u8 *user_buf,
5336 u32 length,
5337 u32 targ_buf,
5338 u32 targ_reply_fn,
5339 u32 targ_reply_arg)
5341 void *osbuf;
5342 WMIX_DSETDATA_REPLY_CMD *data_reply;
5343 u32 size;
5345 size = sizeof(*data_reply) + length;
5347 if (size <= length) {
5348 return A_ERROR;
5351 A_DPRINTF(DBG_WMI,
5352 (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
5354 osbuf = A_NETBUF_ALLOC(size);
5355 if (osbuf == NULL) {
5356 return A_NO_MEMORY;
5358 A_NETBUF_PUT(osbuf, size);
5359 data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5361 data_reply->status = status;
5362 data_reply->targ_buf = targ_buf;
5363 data_reply->targ_reply_fn = targ_reply_fn;
5364 data_reply->targ_reply_arg = targ_reply_arg;
5365 data_reply->length = length;
5367 if (status == 0) {
5368 if (a_copy_from_user(data_reply->buf, user_buf, length)) {
5369 A_NETBUF_FREE(osbuf);
5370 return A_ERROR;
5374 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
5375 NO_SYNC_WMIFLAG));
5377 #endif /* CONFIG_HOST_DSET_SUPPORT */
5380 wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
5382 void *osbuf;
5383 char *cmd;
5385 wps_enable = status;
5387 osbuf = a_netbuf_alloc(sizeof(1));
5388 if (osbuf == NULL) {
5389 return A_NO_MEMORY;
5392 a_netbuf_put(osbuf, sizeof(1));
5394 cmd = (char *)(a_netbuf_to_data(osbuf));
5396 A_MEMZERO(cmd, sizeof(*cmd));
5397 cmd[0] = (status?1:0);
5398 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
5399 NO_SYNC_WMIFLAG));
5402 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
5404 wmi_prof_cfg_cmd(struct wmi_t *wmip,
5405 u32 period,
5406 u32 nbins)
5408 void *osbuf;
5409 WMIX_PROF_CFG_CMD *cmd;
5411 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5412 if (osbuf == NULL) {
5413 return A_NO_MEMORY;
5416 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5418 cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
5419 A_MEMZERO(cmd, sizeof(*cmd));
5420 cmd->period = period;
5421 cmd->nbins = nbins;
5423 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
5427 wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
5429 void *osbuf;
5430 WMIX_PROF_ADDR_SET_CMD *cmd;
5432 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5433 if (osbuf == NULL) {
5434 return A_NO_MEMORY;
5437 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5439 cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
5440 A_MEMZERO(cmd, sizeof(*cmd));
5441 cmd->addr = addr;
5443 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
5447 wmi_prof_start_cmd(struct wmi_t *wmip)
5449 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5453 wmi_prof_stop_cmd(struct wmi_t *wmip)
5455 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5459 wmi_prof_count_get_cmd(struct wmi_t *wmip)
5461 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
5464 /* Called to handle WMIX_PROF_CONT_EVENTID */
5465 static int
5466 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
5468 WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
5470 A_DPRINTF(DBG_WMI,
5471 (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
5472 prof_data->addr, prof_data->count));
5474 A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
5476 return 0;
5478 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5480 #ifdef OS_ROAM_MANAGEMENT
5482 #define ETHERNET_MAC_ADDRESS_LENGTH 6
5484 void
5485 wmi_scan_indication (struct wmi_t *wmip)
5487 struct ieee80211_node_table *nt;
5488 u32 gen;
5489 u32 size;
5490 u32 bsssize;
5491 bss_t *bss;
5492 u32 numbss;
5493 PNDIS_802_11_BSSID_SCAN_INFO psi;
5494 PBYTE pie;
5495 NDIS_802_11_FIXED_IEs *pFixed;
5496 NDIS_802_11_VARIABLE_IEs *pVar;
5497 u32 RateSize;
5499 struct ar6kScanIndication
5501 NDIS_802_11_STATUS_INDICATION ind;
5502 NDIS_802_11_BSSID_SCAN_INFO_LIST slist;
5503 } *pAr6kScanIndEvent;
5505 nt = &wmip->wmi_scan_table;
5507 ++nt->nt_si_gen;
5510 gen = nt->nt_si_gen;
5512 size = offsetof(struct ar6kScanIndication, slist) +
5513 offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
5515 numbss = 0;
5517 IEEE80211_NODE_LOCK(nt);
5519 //calc size
5520 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5521 if (bss->ni_si_gen != gen) {
5522 bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
5523 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5525 #ifdef SUPPORT_WPA2
5526 if (bss->ni_cie.ie_rsn) {
5527 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5529 #endif
5530 if (bss->ni_cie.ie_wpa) {
5531 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5534 // bsssize must be a multiple of 4 to maintain alignment.
5535 bsssize = (bsssize + 3) & ~3;
5537 size += bsssize;
5539 numbss++;
5543 if (0 == numbss)
5545 // RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
5546 ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
5547 IEEE80211_NODE_UNLOCK (nt);
5548 return;
5551 pAr6kScanIndEvent = A_MALLOC(size);
5553 if (NULL == pAr6kScanIndEvent)
5555 IEEE80211_NODE_UNLOCK(nt);
5556 return;
5559 A_MEMZERO(pAr6kScanIndEvent, size);
5561 //copy data
5562 pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
5563 pAr6kScanIndEvent->slist.Version = 1;
5564 pAr6kScanIndEvent->slist.NumItems = numbss;
5566 psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
5568 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5569 if (bss->ni_si_gen != gen) {
5571 bss->ni_si_gen = gen;
5573 //Set scan time
5574 psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
5576 // Copy data to bssid_ex
5577 bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
5578 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5580 #ifdef SUPPORT_WPA2
5581 if (bss->ni_cie.ie_rsn) {
5582 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5584 #endif
5585 if (bss->ni_cie.ie_wpa) {
5586 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5589 // bsssize must be a multiple of 4 to maintain alignment.
5590 bsssize = (bsssize + 3) & ~3;
5592 psi->Bssid.Length = bsssize;
5594 memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
5597 //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
5598 // ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
5599 // RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
5601 psi->Bssid.Ssid.SsidLength = 0;
5602 pie = bss->ni_cie.ie_ssid;
5604 if (pie) {
5605 // Format of SSID IE is:
5606 // Type (1 octet)
5607 // Length (1 octet)
5608 // SSID (Length octets)
5610 // Validation of the IE should have occurred within WMI.
5612 if (pie[1] <= 32) {
5613 psi->Bssid.Ssid.SsidLength = pie[1];
5614 memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
5617 psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
5619 //Post the RSSI value relative to the Standard Noise floor value.
5620 psi->Bssid.Rssi = bss->ni_rssi;
5622 if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
5624 if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
5625 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
5627 else {
5628 psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
5631 else {
5632 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
5635 psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
5636 psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
5637 psi->Bssid.Configuration.ATIMWindow = 0;
5638 psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000;
5639 psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
5641 RateSize = 0;
5642 pie = bss->ni_cie.ie_rates;
5643 if (pie) {
5644 RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
5645 memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
5647 pie = bss->ni_cie.ie_xrates;
5648 if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
5649 memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
5650 (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
5653 // Copy the fixed IEs
5654 psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
5656 pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
5657 memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
5658 pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
5659 pFixed->Capabilities = bss->ni_cie.ie_capInfo;
5661 // Copy selected variable IEs
5663 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
5665 #ifdef SUPPORT_WPA2
5666 // Copy the WPAv2 IE
5667 if (bss->ni_cie.ie_rsn) {
5668 pie = bss->ni_cie.ie_rsn;
5669 psi->Bssid.IELength += pie[1] + 2;
5670 memcpy(pVar, pie, pie[1] + 2);
5671 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5673 #endif
5674 // Copy the WPAv1 IE
5675 if (bss->ni_cie.ie_wpa) {
5676 pie = bss->ni_cie.ie_wpa;
5677 psi->Bssid.IELength += pie[1] + 2;
5678 memcpy(pVar, pie, pie[1] + 2);
5679 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5682 // Advance buffer pointer
5683 psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
5687 IEEE80211_NODE_UNLOCK(nt);
5689 // wmi_free_allnodes(wmip);
5691 // RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
5693 ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
5695 kfree(pAr6kScanIndEvent);
5697 #endif
5699 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5700 u32 size)
5702 u32 index;
5703 u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
5705 /* The list is already in sorted order. Get the next lower value */
5706 for (index = 0; index < size; index ++) {
5707 if (rssi < sq_thresh->upper_threshold[index]) {
5708 threshold = (u8)sq_thresh->upper_threshold[index];
5709 break;
5713 return threshold;
5716 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5717 u32 size)
5719 u32 index;
5720 u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
5722 /* The list is already in sorted order. Get the next lower value */
5723 for (index = 0; index < size; index ++) {
5724 if (rssi > sq_thresh->lower_threshold[index]) {
5725 threshold = (u8)sq_thresh->lower_threshold[index];
5726 break;
5730 return threshold;
5732 static int
5733 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5734 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5736 void *osbuf;
5737 s8 size;
5738 WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
5740 size = sizeof (*cmd);
5742 osbuf = A_NETBUF_ALLOC(size);
5743 if (osbuf == NULL) {
5744 return A_NO_MEMORY;
5747 A_NETBUF_PUT(osbuf, size);
5749 cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5750 A_MEMZERO(cmd, size);
5751 memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
5753 return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5754 NO_SYNC_WMIFLAG));
5756 static int
5757 wmi_send_snr_threshold_params(struct wmi_t *wmip,
5758 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5760 void *osbuf;
5761 s8 size;
5762 WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
5764 size = sizeof (*cmd);
5766 osbuf = A_NETBUF_ALLOC(size);
5767 if (osbuf == NULL) {
5768 return A_NO_MEMORY;
5771 A_NETBUF_PUT(osbuf, size);
5772 cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5773 A_MEMZERO(cmd, size);
5774 memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
5776 return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5777 NO_SYNC_WMIFLAG));
5781 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
5783 void *osbuf;
5784 WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
5786 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5787 if (osbuf == NULL) {
5788 return A_NO_MEMORY;
5791 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5793 alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
5794 A_MEMZERO(alloc_cmd, sizeof(*cmd));
5795 memcpy(alloc_cmd, cmd, sizeof(*cmd));
5797 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5798 NO_SYNC_WMIFLAG));
5801 bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
5803 wmi_get_current_bssid (wmip, id);
5804 return wlan_node_remove (&wmip->wmi_scan_table, id);
5807 int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
5809 wlan_setup_node (&wmip->wmi_scan_table, bss, id);
5810 return 0;
5813 #ifdef ATH_AR6K_11N_SUPPORT
5814 static int
5815 wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5817 WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
5819 A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
5821 return 0;
5825 static int
5826 wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5828 WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
5830 A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
5832 return 0;
5835 static int
5836 wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5838 WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
5840 A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
5842 return 0;
5846 wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5848 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5850 A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
5852 return 0;
5857 wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
5859 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5861 A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
5863 return 0;
5866 #endif
5868 static int
5869 wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5871 WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
5872 A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
5874 return 0;
5877 ////////////////////////////////////////////////////////////////////////////////
5878 //// ////
5879 //// AP mode functions ////
5880 //// ////
5881 ////////////////////////////////////////////////////////////////////////////////
5883 * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
5885 * When AR6K in AP mode, This command will be called after
5886 * changing ssid, channel etc. It will pass the profile to
5887 * target with a flag which will indicate which parameter changed,
5888 * also if this flag is 0, there was no change in parametes, so
5889 * commit cmd will not be sent to target. Without calling this IOCTL
5890 * the changes will not take effect.
5893 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
5895 void *osbuf;
5896 WMI_CONNECT_CMD *cm;
5898 osbuf = A_NETBUF_ALLOC(sizeof(*cm));
5899 if (osbuf == NULL) {
5900 return A_NO_MEMORY;
5903 A_NETBUF_PUT(osbuf, sizeof(*cm));
5904 cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
5905 A_MEMZERO(cm, sizeof(*cm));
5907 memcpy(cm,p,sizeof(*cm));
5909 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
5913 * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
5915 * This command will be used to enable/disable hidden ssid functioanlity of
5916 * beacon. If it is enabled, ssid will be NULL in beacon.
5919 wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
5921 void *osbuf;
5922 WMI_AP_HIDDEN_SSID_CMD *hs;
5924 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
5925 if (osbuf == NULL) {
5926 return A_NO_MEMORY;
5929 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
5930 hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
5931 A_MEMZERO(hs, sizeof(*hs));
5933 hs->hidden_ssid = hidden_ssid;
5935 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
5936 return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
5940 * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
5942 * This command is used to limit max num of STA that can connect
5943 * with this AP. This value should not exceed AP_MAX_NUM_STA (this
5944 * is max num of STA supported by AP). Value was already validated
5945 * in ioctl.c
5948 wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
5950 void *osbuf;
5951 WMI_AP_SET_NUM_STA_CMD *ns;
5953 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
5954 if (osbuf == NULL) {
5955 return A_NO_MEMORY;
5958 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
5959 ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
5960 A_MEMZERO(ns, sizeof(*ns));
5962 ns->num_sta = num_sta;
5964 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
5965 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
5969 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
5971 * This command is used to send list of mac of STAs which will
5972 * be allowed to connect with this AP. When this list is empty
5973 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5976 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
5978 void *osbuf;
5979 WMI_AP_ACL_MAC_CMD *a;
5981 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
5982 if (osbuf == NULL) {
5983 return A_NO_MEMORY;
5986 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
5987 a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
5988 A_MEMZERO(a, sizeof(*a));
5989 memcpy(a,acl,sizeof(*acl));
5991 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
5995 * IOCTL: AR6000_XIOCTL_AP_SET_MLME
5997 * This command is used to send list of mac of STAs which will
5998 * be allowed to connect with this AP. When this list is empty
5999 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
6002 wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
6004 void *osbuf;
6005 WMI_AP_SET_MLME_CMD *mlme;
6007 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
6008 if (osbuf == NULL) {
6009 return A_NO_MEMORY;
6012 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
6013 mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
6014 A_MEMZERO(mlme, sizeof(*mlme));
6016 mlme->cmd = cmd;
6017 memcpy(mlme->mac, mac, ATH_MAC_LEN);
6018 mlme->reason = reason;
6020 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
6023 static int
6024 wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
6026 WMI_PSPOLL_EVENT *ev;
6028 if (len < sizeof(WMI_PSPOLL_EVENT)) {
6029 return A_EINVAL;
6031 ev = (WMI_PSPOLL_EVENT *)datap;
6033 A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
6034 return 0;
6037 static int
6038 wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6040 A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
6041 return 0;
6044 #ifdef WAPI_ENABLE
6045 static int
6046 wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6048 u8 *ev;
6050 if (len < 7) {
6051 return A_EINVAL;
6053 ev = (u8 *)datap;
6055 A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
6056 return 0;
6058 #endif
6061 wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
6063 WMI_AP_SET_PVB_CMD *cmd;
6064 void *osbuf = NULL;
6066 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
6067 if (osbuf == NULL) {
6068 return A_NO_MEMORY;
6071 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
6072 cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
6073 A_MEMZERO(cmd, sizeof(*cmd));
6075 cmd->aid = aid;
6076 cmd->flag = flag;
6078 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
6082 wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
6084 WMI_AP_CONN_INACT_CMD *cmd;
6085 void *osbuf = NULL;
6087 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
6088 if (osbuf == NULL) {
6089 return A_NO_MEMORY;
6092 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
6093 cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
6094 A_MEMZERO(cmd, sizeof(*cmd));
6096 cmd->period = period;
6098 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
6102 wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
6104 WMI_AP_PROT_SCAN_TIME_CMD *cmd;
6105 void *osbuf = NULL;
6107 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6108 if (osbuf == NULL) {
6109 return A_NO_MEMORY;
6112 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6113 cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
6114 A_MEMZERO(cmd, sizeof(*cmd));
6116 cmd->period_min = period;
6117 cmd->dwell_ms = dwell;
6119 return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
6123 wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
6125 WMI_AP_SET_DTIM_CMD *cmd;
6126 void *osbuf = NULL;
6128 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
6129 if (osbuf == NULL) {
6130 return A_NO_MEMORY;
6133 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
6134 cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
6135 A_MEMZERO(cmd, sizeof(*cmd));
6137 cmd->dtim = dtim;
6139 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
6143 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
6145 * This command is used to set ACL policay. While changing policy, if you
6146 * want to retain the existing MAC addresses in the ACL list, policy should be
6147 * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
6148 * If there is no chage in policy, the list will be intact.
6151 wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
6153 void *osbuf;
6154 WMI_AP_ACL_POLICY_CMD *po;
6156 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
6157 if (osbuf == NULL) {
6158 return A_NO_MEMORY;
6161 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
6162 po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
6163 A_MEMZERO(po, sizeof(*po));
6165 po->policy = policy;
6167 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
6171 wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
6173 void *osbuf;
6174 WMI_AP_SET_11BG_RATESET_CMD *rs;
6176 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6177 if (osbuf == NULL) {
6178 return A_NO_MEMORY;
6181 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6182 rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
6183 A_MEMZERO(rs, sizeof(*rs));
6185 rs->rateset = rateset;
6187 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
6190 #ifdef ATH_AR6K_11N_SUPPORT
6192 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
6194 void *osbuf;
6195 WMI_SET_HT_CAP_CMD *htCap;
6196 u8 band;
6198 osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
6199 if (osbuf == NULL) {
6200 return A_NO_MEMORY;
6203 A_NETBUF_PUT(osbuf, sizeof(*htCap));
6205 band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
6206 wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
6208 htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
6209 A_MEMZERO(htCap, sizeof(*htCap));
6210 memcpy(htCap, cmd, sizeof(*htCap));
6212 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6213 NO_SYNC_WMIFLAG));
6217 wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
6219 void *osbuf;
6220 WMI_SET_HT_OP_CMD *htInfo;
6222 osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
6223 if (osbuf == NULL) {
6224 return A_NO_MEMORY;
6227 A_NETBUF_PUT(osbuf, sizeof(*htInfo));
6229 htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
6230 A_MEMZERO(htInfo, sizeof(*htInfo));
6231 htInfo->sta_chan_width = sta_chan_width;
6233 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
6234 NO_SYNC_WMIFLAG));
6236 #endif
6239 wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
6241 void *osbuf;
6242 WMI_SET_TX_SELECT_RATES_CMD *pData;
6244 osbuf = A_NETBUF_ALLOC(sizeof(*pData));
6245 if (osbuf == NULL) {
6246 return A_NO_MEMORY;
6249 A_NETBUF_PUT(osbuf, sizeof(*pData));
6251 pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
6252 memcpy(pData, pMaskArray, sizeof(*pData));
6254 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6255 NO_SYNC_WMIFLAG));
6260 wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
6262 void *osbuf;
6263 WMI_HCI_CMD *cmd;
6265 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
6266 if (osbuf == NULL) {
6267 return A_NO_MEMORY;
6270 A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
6271 cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
6273 cmd->cmd_buf_sz = sz;
6274 memcpy(cmd->buf, buf, sz);
6275 return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6278 #ifdef ATH_AR6K_11N_SUPPORT
6280 wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
6282 void *osbuf;
6283 WMI_ALLOW_AGGR_CMD *cmd;
6285 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6286 if (osbuf == NULL) {
6287 return A_NO_MEMORY;
6290 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6292 cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
6293 cmd->tx_allow_aggr = tx_tidmask;
6294 cmd->rx_allow_aggr = rx_tidmask;
6296 return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
6300 wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
6302 void *osbuf;
6303 WMI_ADDBA_REQ_CMD *cmd;
6305 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6306 if (osbuf == NULL) {
6307 return A_NO_MEMORY;
6310 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6312 cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6313 cmd->tid = tid;
6315 return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6319 wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
6321 void *osbuf;
6322 WMI_DELBA_REQ_CMD *cmd;
6324 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6325 if (osbuf == NULL) {
6326 return A_NO_MEMORY;
6329 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6331 cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6332 cmd->tid = tid;
6333 cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */
6335 /* Delete the local aggr state, on host */
6336 return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6338 #endif
6341 wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
6342 bool rxDot11Hdr, bool defragOnHost)
6344 void *osbuf;
6345 WMI_RX_FRAME_FORMAT_CMD *cmd;
6347 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6348 if (osbuf == NULL) {
6349 return A_NO_MEMORY;
6352 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6354 cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
6355 cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6356 cmd->defragOnHost = (defragOnHost==true)? 1:0;
6357 cmd->metaVersion = rxMetaVersion; /* */
6359 /* Delete the local aggr state, on host */
6360 return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
6365 wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
6367 void *osbuf;
6368 WMI_SET_THIN_MODE_CMD *cmd;
6370 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6371 if (osbuf == NULL) {
6372 return A_NO_MEMORY;
6375 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6377 cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
6378 cmd->enable = (bThinMode==true)? 1:0;
6380 /* Delete the local aggr state, on host */
6381 return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
6386 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
6388 void *osbuf;
6389 WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
6391 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6392 if (osbuf == NULL) {
6393 return A_NO_MEMORY;
6396 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6398 cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
6399 A_MEMZERO(cmd, sizeof(*cmd));
6400 cmd->precedence = precedence;
6402 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
6403 NO_SYNC_WMIFLAG));
6407 wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
6409 void *osbuf;
6410 WMI_SET_PMK_CMD *p;
6412 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
6413 if (osbuf == NULL) {
6414 return A_NO_MEMORY;
6417 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
6419 p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
6420 A_MEMZERO(p, sizeof(*p));
6422 memcpy(p->pmk, pmk, WMI_PMK_LEN);
6424 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6428 wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
6430 void *osbuf;
6431 WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
6433 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6434 if (osbuf == NULL) {
6435 return A_NO_MEMORY;
6438 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6440 p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
6441 memset(p, 0, sizeof(*p));
6443 p->threshold = cmd->threshold;
6445 return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
6449 wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
6451 void *osbuf;
6452 WMI_SET_TX_SGI_PARAM_CMD *cmd;
6454 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6455 if (osbuf == NULL) {
6456 return A_NO_MEMORY ;
6459 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6461 cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
6462 A_MEMZERO(cmd, sizeof(*cmd));
6463 cmd->sgiMask = sgiMask;
6464 cmd->sgiPERThreshold = sgiPERThreshold;
6465 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
6466 NO_SYNC_WMIFLAG));
6469 bss_t *
6470 wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
6471 u32 ssidLength,
6472 u32 dot11AuthMode, u32 authMode,
6473 u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
6475 bss_t *node = NULL;
6476 node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
6477 ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
6479 return node;
6482 u16 wmi_ieee2freq (int chan)
6484 u16 freq = 0;
6485 freq = wlan_ieee2freq (chan);
6486 return freq;
6490 u32 wmi_freq2ieee (u16 freq)
6492 u16 chan = 0;
6493 chan = wlan_freq2ieee (freq);
6494 return chan;