Staging: merge 2.6.39-rc3 into staging-next
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / ath6kl / wmi / wmi.c
blob1575c7fbaba5fa02f97cbe91bdb8bfc904fedc10
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 static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
185 static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
186 static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
187 static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
188 static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
189 static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
191 #ifdef WAPI_ENABLE
192 static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
193 int len);
194 #endif
196 #if defined(UNDER_CE)
197 #if defined(NDIS51_MINIPORT)
198 unsigned int processDot11Hdr = 0;
199 #else
200 unsigned int processDot11Hdr = 1;
201 #endif
202 #else
203 extern unsigned int processDot11Hdr;
204 #endif
206 int wps_enable;
207 static const s32 wmi_rateTable[][2] = {
208 //{W/O SGI, with SGI}
209 {1000, 1000},
210 {2000, 2000},
211 {5500, 5500},
212 {11000, 11000},
213 {6000, 6000},
214 {9000, 9000},
215 {12000, 12000},
216 {18000, 18000},
217 {24000, 24000},
218 {36000, 36000},
219 {48000, 48000},
220 {54000, 54000},
221 {6500, 7200},
222 {13000, 14400},
223 {19500, 21700},
224 {26000, 28900},
225 {39000, 43300},
226 {52000, 57800},
227 {58500, 65000},
228 {65000, 72200},
229 {13500, 15000},
230 {27000, 30000},
231 {40500, 45000},
232 {54000, 60000},
233 {81000, 90000},
234 {108000, 120000},
235 {121500, 135000},
236 {135000, 150000},
237 {0, 0}};
239 #define MODE_A_SUPPORT_RATE_START ((s32) 4)
240 #define MODE_A_SUPPORT_RATE_STOP ((s32) 11)
242 #define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
243 #define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
245 #define MODE_B_SUPPORT_RATE_START ((s32) 0)
246 #define MODE_B_SUPPORT_RATE_STOP ((s32) 3)
248 #define MODE_G_SUPPORT_RATE_START ((s32) 0)
249 #define MODE_G_SUPPORT_RATE_STOP ((s32) 11)
251 #define MODE_GHT20_SUPPORT_RATE_START ((s32) 0)
252 #define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19)
254 #define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1)
256 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
257 const u8 up_to_ac[]= {
258 WMM_AC_BE,
259 WMM_AC_BK,
260 WMM_AC_BK,
261 WMM_AC_BE,
262 WMM_AC_VI,
263 WMM_AC_VI,
264 WMM_AC_VO,
265 WMM_AC_VO,
268 /* This stuff is used when we want a simple layer-3 visibility */
269 typedef PREPACK struct _iphdr {
270 u8 ip_ver_hdrlen; /* version and hdr length */
271 u8 ip_tos; /* type of service */
272 u16 ip_len; /* total length */
273 u16 ip_id; /* identification */
274 s16 ip_off; /* fragment offset field */
275 #define IP_DF 0x4000 /* dont fragment flag */
276 #define IP_MF 0x2000 /* more fragments flag */
277 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
278 u8 ip_ttl; /* time to live */
279 u8 ip_p; /* protocol */
280 u16 ip_sum; /* checksum */
281 u8 ip_src[4]; /* source and dest address */
282 u8 ip_dst[4];
283 } POSTPACK iphdr;
285 static s16 rssi_event_value = 0;
286 static s16 snr_event_value = 0;
288 bool is_probe_ssid = false;
290 void *
291 wmi_init(void *devt)
293 struct wmi_t *wmip;
295 A_REGISTER_MODULE_DEBUG_INFO(wmi);
297 wmip = A_MALLOC (sizeof(struct wmi_t));
298 if (wmip == NULL) {
299 return (NULL);
301 A_MEMZERO(wmip, sizeof(struct wmi_t ));
302 #ifdef THREAD_X
303 INIT_WMI_LOCK(wmip);
304 #else
305 A_MUTEX_INIT(&wmip->wmi_lock);
306 #endif
307 wmip->wmi_devt = devt;
308 wlan_node_table_init(wmip, &wmip->wmi_scan_table);
309 wmi_qos_state_init(wmip);
311 wmip->wmi_powerMode = REC_POWER;
312 wmip->wmi_phyMode = WMI_11G_MODE;
314 wmip->wmi_pair_crypto_type = NONE_CRYPT;
315 wmip->wmi_grp_crypto_type = NONE_CRYPT;
317 wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1;
318 wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1;
320 return (wmip);
323 void
324 wmi_qos_state_init(struct wmi_t *wmip)
326 u8 i;
328 if (wmip == NULL) {
329 return;
331 LOCK_WMI(wmip);
333 /* Initialize QoS States */
334 wmip->wmi_numQoSStream = 0;
336 wmip->wmi_fatPipeExists = 0;
338 for (i=0; i < WMM_NUM_AC; i++) {
339 wmip->wmi_streamExistsForAC[i]=0;
342 UNLOCK_WMI(wmip);
344 A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
347 void
348 wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid)
350 A_ASSERT( eid != ENDPOINT_UNUSED);
351 wmip->wmi_endpoint_id = eid;
354 HTC_ENDPOINT_ID
355 wmi_get_control_ep(struct wmi_t * wmip)
357 return(wmip->wmi_endpoint_id);
360 void
361 wmi_shutdown(struct wmi_t *wmip)
363 if (wmip != NULL) {
364 wlan_node_table_cleanup(&wmip->wmi_scan_table);
365 if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
366 #ifdef THREAD_X
367 DELETE_WMI_LOCK(&wmip);
368 #else
369 A_MUTEX_DELETE(&wmip->wmi_lock);
370 #endif
372 kfree(wmip);
377 * performs DIX to 802.3 encapsulation for transmit packets.
378 * uses passed in buffer. Returns buffer or NULL if failed.
379 * Assumes the entire DIX header is contigous and that there is
380 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
383 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
385 u8 *datap;
386 u16 typeorlen;
387 ATH_MAC_HDR macHdr;
388 ATH_LLC_SNAP_HDR *llcHdr;
390 A_ASSERT(osbuf != NULL);
392 if (A_NETBUF_HEADROOM(osbuf) <
393 (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
395 return A_NO_MEMORY;
398 datap = A_NETBUF_DATA(osbuf);
400 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
402 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
404 * packet is already in 802.3 format - return success
406 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
407 return (0);
411 * Save mac fields and length to be inserted later
413 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
414 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
415 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
416 sizeof(ATH_LLC_SNAP_HDR));
419 * Make room for LLC+SNAP headers
421 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
422 return A_NO_MEMORY;
424 datap = A_NETBUF_DATA(osbuf);
426 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
428 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
429 llcHdr->dsap = 0xAA;
430 llcHdr->ssap = 0xAA;
431 llcHdr->cntl = 0x03;
432 llcHdr->orgCode[0] = 0x0;
433 llcHdr->orgCode[1] = 0x0;
434 llcHdr->orgCode[2] = 0x0;
435 llcHdr->etherType = typeorlen;
437 return (0);
440 int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
442 switch(*pVersion){
443 case 0:
444 return (0);
445 case WMI_META_VERSION_1:
447 WMI_TX_META_V1 *pV1= NULL;
448 A_ASSERT(osbuf != NULL);
449 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
450 return A_NO_MEMORY;
453 pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf);
454 /* the pktID is used in conjunction with txComplete messages
455 * allowing the target to notify which tx requests have been
456 * completed and how. */
457 pV1->pktID = 0;
458 /* the ratePolicyID allows the host to specify which rate policy
459 * to use for transmitting this packet. 0 means use default behavior. */
460 pV1->ratePolicyID = 0;
461 A_ASSERT(pVersion != NULL);
462 /* the version must be used to populate the meta field of the WMI_DATA_HDR */
463 *pVersion = WMI_META_VERSION_1;
464 return (0);
466 case WMI_META_VERSION_2:
468 WMI_TX_META_V2 *pV2 ;
469 A_ASSERT(osbuf != NULL);
470 if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
471 return A_NO_MEMORY;
473 pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
474 memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
475 return (0);
477 default:
478 return (0);
482 /* Adds a WMI data header */
484 wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
485 WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
487 WMI_DATA_HDR *dtHdr;
488 // u8 metaVersion = 0;
489 int status;
491 A_ASSERT(osbuf != NULL);
493 /* adds the meta data field after the wmi data hdr. If metaVersion
494 * is returns 0 then no meta field was added. */
495 if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
496 return status;
499 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
500 return A_NO_MEMORY;
503 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
504 A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR));
506 WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType);
507 WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type);
509 if (bMoreData) {
510 WMI_DATA_HDR_SET_MORE_BIT(dtHdr);
513 WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
514 //dtHdr->rssi = 0;
516 return (0);
520 u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
522 u8 *datap;
523 u8 trafficClass = WMM_AC_BE;
524 u16 ipType = IP_ETHERTYPE;
525 WMI_DATA_HDR *dtHdr;
526 u8 streamExists = 0;
527 u8 userPriority;
528 u32 hdrsize, metasize;
529 ATH_LLC_SNAP_HDR *llcHdr;
531 WMI_CREATE_PSTREAM_CMD cmd;
533 A_ASSERT(osbuf != NULL);
536 // Initialize header size
538 hdrsize = 0;
540 datap = A_NETBUF_DATA(osbuf);
541 dtHdr = (WMI_DATA_HDR *)datap;
542 metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0;
544 if (!wmmEnabled)
546 /* If WMM is disabled all traffic goes as BE traffic */
547 userPriority = 0;
549 else
551 if (processDot11Hdr)
553 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
554 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
555 hdrsize);
559 else
561 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
562 sizeof(ATH_MAC_HDR));
565 if (llcHdr->etherType == A_CPU2BE16(ipType))
567 /* Extract the endpoint info from the TOS field in the IP header */
569 userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
571 else
573 userPriority = layer2Priority & 0x7;
578 /* workaround for WMM S5 */
579 if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority)))
581 userPriority = 1;
584 trafficClass = convert_userPriority_to_trafficClass(userPriority);
586 WMI_DATA_HDR_SET_UP(dtHdr, userPriority);
587 /* lower 3-bits are 802.1d priority */
588 //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;
590 LOCK_WMI(wmip);
591 streamExists = wmip->wmi_fatPipeExists;
592 UNLOCK_WMI(wmip);
594 if (!(streamExists & (1 << trafficClass)))
597 A_MEMZERO(&cmd, sizeof(cmd));
598 cmd.trafficClass = trafficClass;
599 cmd.userPriority = userPriority;
600 cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
601 /* Implicit streams are created with TSID 0xFF */
603 cmd.tsid = WMI_IMPLICIT_PSTREAM;
604 wmi_create_pstream_cmd(wmip, &cmd);
607 return trafficClass;
611 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
613 u8 *datap;
614 u16 typeorlen;
615 ATH_MAC_HDR macHdr;
616 ATH_LLC_SNAP_HDR *llcHdr;
617 struct ieee80211_frame *wh;
618 u32 hdrsize;
620 A_ASSERT(osbuf != NULL);
622 if (A_NETBUF_HEADROOM(osbuf) <
623 (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
625 return A_NO_MEMORY;
628 datap = A_NETBUF_DATA(osbuf);
630 typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
632 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
634 * packet is already in 802.3 format - return success
636 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
637 goto AddDot11Hdr;
641 * Save mac fields and length to be inserted later
643 memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
644 memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
645 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
646 sizeof(ATH_LLC_SNAP_HDR));
648 // Remove the Ethernet hdr
649 A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR));
651 * Make room for LLC+SNAP headers
653 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
654 return A_NO_MEMORY;
656 datap = A_NETBUF_DATA(osbuf);
658 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
659 llcHdr->dsap = 0xAA;
660 llcHdr->ssap = 0xAA;
661 llcHdr->cntl = 0x03;
662 llcHdr->orgCode[0] = 0x0;
663 llcHdr->orgCode[1] = 0x0;
664 llcHdr->orgCode[2] = 0x0;
665 llcHdr->etherType = typeorlen;
667 AddDot11Hdr:
668 /* Make room for 802.11 hdr */
669 if (wmip->wmi_is_wmm_enabled)
671 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
672 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
674 return A_NO_MEMORY;
676 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
677 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS;
679 else
681 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
682 if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
684 return A_NO_MEMORY;
686 wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf);
687 wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA;
689 /* Setup the SA & DA */
690 IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac);
692 if (mode == INFRA_NETWORK) {
693 IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac);
695 else if (mode == ADHOC_NETWORK) {
696 IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
699 return (0);
703 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
705 u8 *datap;
706 struct ieee80211_frame *pwh,wh;
707 u8 type,subtype;
708 ATH_LLC_SNAP_HDR *llcHdr;
709 ATH_MAC_HDR macHdr;
710 u32 hdrsize;
712 A_ASSERT(osbuf != NULL);
713 datap = A_NETBUF_DATA(osbuf);
715 pwh = (struct ieee80211_frame *)datap;
716 type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
717 subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
719 memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
721 /* strip off the 802.11 hdr*/
722 if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
723 hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
724 A_NETBUF_PULL(osbuf, hdrsize);
725 } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
726 A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
729 datap = A_NETBUF_DATA(osbuf);
730 llcHdr = (ATH_LLC_SNAP_HDR *)(datap);
732 macHdr.typeOrLen = llcHdr->etherType;
733 A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac));
734 A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac));
736 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
737 case IEEE80211_FC1_DIR_NODS:
738 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
739 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
740 break;
741 case IEEE80211_FC1_DIR_TODS:
742 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3);
743 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2);
744 break;
745 case IEEE80211_FC1_DIR_FROMDS:
746 IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1);
747 IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3);
748 break;
749 case IEEE80211_FC1_DIR_DSTODS:
750 break;
753 // Remove the LLC Hdr.
754 A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR));
756 // Insert the ATH MAC hdr.
758 A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
759 datap = A_NETBUF_DATA(osbuf);
761 memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
763 return 0;
767 * performs 802.3 to DIX encapsulation for received packets.
768 * Assumes the entire 802.3 header is contigous.
771 wmi_dot3_2_dix(void *osbuf)
773 u8 *datap;
774 ATH_MAC_HDR macHdr;
775 ATH_LLC_SNAP_HDR *llcHdr;
777 A_ASSERT(osbuf != NULL);
778 datap = A_NETBUF_DATA(osbuf);
780 memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
781 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
782 macHdr.typeOrLen = llcHdr->etherType;
784 if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
785 return A_NO_MEMORY;
788 datap = A_NETBUF_DATA(osbuf);
790 memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
792 return (0);
796 * Removes a WMI data header
799 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
801 A_ASSERT(osbuf != NULL);
803 return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
806 void
807 wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
809 wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
813 * WMI Extended Event received from Target.
816 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
818 WMIX_CMD_HDR *cmd;
819 u16 id;
820 u8 *datap;
821 u32 len;
822 int status = 0;
824 if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
825 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
826 wmip->wmi_stats.cmd_len_err++;
827 return A_ERROR;
830 cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
831 id = cmd->commandId;
833 if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
834 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
835 wmip->wmi_stats.cmd_len_err++;
836 return A_ERROR;
839 datap = A_NETBUF_DATA(osbuf);
840 len = A_NETBUF_LEN(osbuf);
842 switch (id) {
843 case (WMIX_DSETOPENREQ_EVENTID):
844 status = wmi_dset_open_req_rx(wmip, datap, len);
845 break;
846 #ifdef CONFIG_HOST_DSET_SUPPORT
847 case (WMIX_DSETCLOSE_EVENTID):
848 status = wmi_dset_close_rx(wmip, datap, len);
849 break;
850 case (WMIX_DSETDATAREQ_EVENTID):
851 status = wmi_dset_data_req_rx(wmip, datap, len);
852 break;
853 #endif /* CONFIG_HOST_DSET_SUPPORT */
854 case (WMIX_HB_CHALLENGE_RESP_EVENTID):
855 wmi_hbChallengeResp_rx(wmip, datap, len);
856 break;
857 case (WMIX_DBGLOG_EVENTID):
858 wmi_dbglog_event_rx(wmip, datap, len);
859 break;
860 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
861 case (WMIX_PROF_COUNT_EVENTID):
862 wmi_prof_count_rx(wmip, datap, len);
863 break;
864 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
865 default:
866 A_DPRINTF(DBG_WMI|DBG_ERROR,
867 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
868 wmip->wmi_stats.cmd_id_err++;
869 status = A_ERROR;
870 break;
873 return status;
877 * Control Path
879 u32 cmdRecvNum;
882 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
884 WMI_CMD_HDR *cmd;
885 u16 id;
886 u8 *datap;
887 u32 len, i, loggingReq;
888 int status = 0;
890 A_ASSERT(osbuf != NULL);
891 if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
892 A_NETBUF_FREE(osbuf);
893 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
894 wmip->wmi_stats.cmd_len_err++;
895 return A_ERROR;
898 cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
899 id = cmd->commandId;
901 if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
902 A_NETBUF_FREE(osbuf);
903 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
904 wmip->wmi_stats.cmd_len_err++;
905 return A_ERROR;
908 datap = A_NETBUF_DATA(osbuf);
909 len = A_NETBUF_LEN(osbuf);
911 loggingReq = 0;
913 ar6000_get_driver_cfg(wmip->wmi_devt,
914 AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
915 &loggingReq);
917 if(loggingReq) {
918 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
919 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
920 for(i = 0; i < len; i++)
921 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
922 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
925 LOCK_WMI(wmip);
926 cmdRecvNum++;
927 UNLOCK_WMI(wmip);
929 switch (id) {
930 case (WMI_GET_BITRATE_CMDID):
931 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
932 status = wmi_bitrate_reply_rx(wmip, datap, len);
933 break;
934 case (WMI_GET_CHANNEL_LIST_CMDID):
935 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
936 status = wmi_channelList_reply_rx(wmip, datap, len);
937 break;
938 case (WMI_GET_TX_PWR_CMDID):
939 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
940 status = wmi_txPwr_reply_rx(wmip, datap, len);
941 break;
942 case (WMI_READY_EVENTID):
943 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
944 status = wmi_ready_event_rx(wmip, datap, len);
945 A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
946 break;
947 case (WMI_CONNECT_EVENTID):
948 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
949 status = wmi_connect_event_rx(wmip, datap, len);
950 break;
951 case (WMI_DISCONNECT_EVENTID):
952 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
953 status = wmi_disconnect_event_rx(wmip, datap, len);
954 break;
955 case (WMI_PEER_NODE_EVENTID):
956 A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG));
957 status = wmi_peer_node_event_rx(wmip, datap, len);
958 break;
959 case (WMI_TKIP_MICERR_EVENTID):
960 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
961 status = wmi_tkip_micerr_event_rx(wmip, datap, len);
962 break;
963 case (WMI_BSSINFO_EVENTID):
964 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
967 * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR
968 * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer
969 * and reconstruct the WMI_BSS_INFO_HDR in its place
971 WMI_BSS_INFO_HDR2 bih2;
972 WMI_BSS_INFO_HDR *bih;
973 memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
975 A_NETBUF_PUSH(osbuf, 4);
976 datap = A_NETBUF_DATA(osbuf);
977 len = A_NETBUF_LEN(osbuf);
978 bih = (WMI_BSS_INFO_HDR *)datap;
980 bih->channel = bih2.channel;
981 bih->frameType = bih2.frameType;
982 bih->snr = bih2.snr;
983 bih->rssi = bih2.snr - 95;
984 bih->ieMask = bih2.ieMask;
985 memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
987 status = wmi_bssInfo_event_rx(wmip, datap, len);
989 break;
990 case (WMI_REGDOMAIN_EVENTID):
991 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
992 status = wmi_regDomain_event_rx(wmip, datap, len);
993 break;
994 case (WMI_PSTREAM_TIMEOUT_EVENTID):
995 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
996 status = wmi_pstream_timeout_event_rx(wmip, datap, len);
997 break;
998 case (WMI_NEIGHBOR_REPORT_EVENTID):
999 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
1000 status = wmi_neighborReport_event_rx(wmip, datap, len);
1001 break;
1002 case (WMI_SCAN_COMPLETE_EVENTID):
1003 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
1004 status = wmi_scanComplete_rx(wmip, datap, len);
1005 break;
1006 case (WMI_CMDERROR_EVENTID):
1007 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
1008 status = wmi_errorEvent_rx(wmip, datap, len);
1009 break;
1010 case (WMI_REPORT_STATISTICS_EVENTID):
1011 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
1012 status = wmi_statsEvent_rx(wmip, datap, len);
1013 break;
1014 case (WMI_RSSI_THRESHOLD_EVENTID):
1015 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
1016 status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
1017 break;
1018 case (WMI_ERROR_REPORT_EVENTID):
1019 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
1020 status = wmi_reportErrorEvent_rx(wmip, datap, len);
1021 break;
1022 case (WMI_OPT_RX_FRAME_EVENTID):
1023 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
1024 status = wmi_opt_frame_event_rx(wmip, datap, len);
1025 break;
1026 case (WMI_REPORT_ROAM_TBL_EVENTID):
1027 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
1028 status = wmi_roam_tbl_event_rx(wmip, datap, len);
1029 break;
1030 case (WMI_EXTENSION_EVENTID):
1031 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
1032 status = wmi_control_rx_xtnd(wmip, osbuf);
1033 break;
1034 case (WMI_CAC_EVENTID):
1035 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
1036 status = wmi_cac_event_rx(wmip, datap, len);
1037 break;
1038 case (WMI_CHANNEL_CHANGE_EVENTID):
1039 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG));
1040 status = wmi_channel_change_event_rx(wmip, datap, len);
1041 break;
1042 case (WMI_REPORT_ROAM_DATA_EVENTID):
1043 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
1044 status = wmi_roam_data_event_rx(wmip, datap, len);
1045 break;
1046 #ifdef CONFIG_HOST_TCMD_SUPPORT
1047 case (WMI_TEST_EVENTID):
1048 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
1049 status = wmi_tcmd_test_report_rx(wmip, datap, len);
1050 break;
1051 #endif
1052 case (WMI_GET_FIXRATES_CMDID):
1053 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
1054 status = wmi_ratemask_reply_rx(wmip, datap, len);
1055 break;
1056 case (WMI_TX_RETRY_ERR_EVENTID):
1057 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
1058 status = wmi_txRetryErrEvent_rx(wmip, datap, len);
1059 break;
1060 case (WMI_SNR_THRESHOLD_EVENTID):
1061 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
1062 status = wmi_snrThresholdEvent_rx(wmip, datap, len);
1063 break;
1064 case (WMI_LQ_THRESHOLD_EVENTID):
1065 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
1066 status = wmi_lqThresholdEvent_rx(wmip, datap, len);
1067 break;
1068 case (WMI_APLIST_EVENTID):
1069 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
1070 status = wmi_aplistEvent_rx(wmip, datap, len);
1071 break;
1072 case (WMI_GET_KEEPALIVE_CMDID):
1073 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
1074 status = wmi_keepalive_reply_rx(wmip, datap, len);
1075 break;
1076 case (WMI_GET_WOW_LIST_EVENTID):
1077 status = wmi_get_wow_list_event_rx(wmip, datap, len);
1078 break;
1079 case (WMI_GET_PMKID_LIST_EVENTID):
1080 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
1081 status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
1082 break;
1083 case (WMI_PSPOLL_EVENTID):
1084 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG));
1085 status = wmi_pspoll_event_rx(wmip, datap, len);
1086 break;
1087 case (WMI_DTIMEXPIRY_EVENTID):
1088 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG));
1089 status = wmi_dtimexpiry_event_rx(wmip, datap, len);
1090 break;
1091 case (WMI_SET_PARAMS_REPLY_EVENTID):
1092 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1093 status = wmi_set_params_event_rx(wmip, datap, len);
1094 break;
1095 case (WMI_ACM_REJECT_EVENTID):
1096 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG));
1097 status = wmi_acm_reject_event_rx(wmip, datap, len);
1098 break;
1099 case (WMI_ADDBA_REQ_EVENTID):
1100 status = wmi_addba_req_event_rx(wmip, datap, len);
1101 break;
1102 case (WMI_ADDBA_RESP_EVENTID):
1103 status = wmi_addba_resp_event_rx(wmip, datap, len);
1104 break;
1105 case (WMI_DELBA_REQ_EVENTID):
1106 status = wmi_delba_req_event_rx(wmip, datap, len);
1107 break;
1108 case (WMI_REPORT_BTCOEX_CONFIG_EVENTID):
1109 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG));
1110 status = wmi_btcoex_config_event_rx(wmip, datap, len);
1111 break;
1112 case (WMI_REPORT_BTCOEX_STATS_EVENTID):
1113 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG));
1114 status = wmi_btcoex_stats_event_rx(wmip, datap, len);
1115 break;
1116 case (WMI_TX_COMPLETE_EVENTID):
1118 int index;
1119 TX_COMPLETE_MSG_V1 *pV1;
1120 WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap;
1121 A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType);
1123 for(index = 0 ; index < pEv->numMessages ; index++) {
1124 pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1));
1125 A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures);
1128 break;
1129 case (WMI_HCI_EVENT_EVENTID):
1130 status = wmi_hci_event_rx(wmip, datap, len);
1131 break;
1132 #ifdef WAPI_ENABLE
1133 case (WMI_WAPI_REKEY_EVENTID):
1134 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG));
1135 status = wmi_wapi_rekey_event_rx(wmip, datap, len);
1136 break;
1137 #endif
1138 default:
1139 A_DPRINTF(DBG_WMI|DBG_ERROR,
1140 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
1141 wmip->wmi_stats.cmd_id_err++;
1142 status = A_ERROR;
1143 break;
1146 A_NETBUF_FREE(osbuf);
1148 return status;
1151 /* Send a "simple" wmi command -- one with no arguments */
1152 static int
1153 wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
1155 void *osbuf;
1157 osbuf = A_NETBUF_ALLOC(0);
1158 if (osbuf == NULL) {
1159 return A_NO_MEMORY;
1162 return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1165 /* Send a "simple" extended wmi command -- one with no arguments.
1166 Enabling this command only if GPIO or profiling support is enabled.
1167 This is to suppress warnings on some platforms */
1168 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1169 static int
1170 wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
1172 void *osbuf;
1174 osbuf = A_NETBUF_ALLOC(0);
1175 if (osbuf == NULL) {
1176 return A_NO_MEMORY;
1179 return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG));
1181 #endif
1183 static int
1184 wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1186 WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
1188 if (len < sizeof(WMI_READY_EVENT)) {
1189 return A_EINVAL;
1191 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1192 wmip->wmi_ready = true;
1193 A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
1194 ev->sw_version, ev->abi_version);
1196 return 0;
1199 #define LE_READ_4(p) \
1200 ((u32) \
1201 ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \
1202 (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
1204 static int __inline
1205 iswmmoui(const u8 *frm)
1207 return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
1210 static int __inline
1211 iswmmparam(const u8 *frm)
1213 return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
1217 static int
1218 wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1220 WMI_CONNECT_EVENT *ev;
1221 u8 *pie,*peie;
1223 if (len < sizeof(WMI_CONNECT_EVENT))
1225 return A_EINVAL;
1227 ev = (WMI_CONNECT_EVENT *)datap;
1229 A_DPRINTF(DBG_WMI,
1230 (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
1231 DBGARG, ev->channel,
1232 ev->bssid[0], ev->bssid[1], ev->bssid[2],
1233 ev->bssid[3], ev->bssid[4], ev->bssid[5]));
1235 memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
1237 /* initialize pointer to start of assoc rsp IEs */
1238 pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
1239 sizeof(u16) + /* capinfo*/
1240 sizeof(u16) + /* status Code */
1241 sizeof(u16) ; /* associd */
1243 /* initialize pointer to end of assoc rsp IEs */
1244 peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
1246 while (pie < peie)
1248 switch (*pie)
1250 case IEEE80211_ELEMID_VENDOR:
1251 if (iswmmoui(pie))
1253 if(iswmmparam (pie))
1255 wmip->wmi_is_wmm_enabled = true;
1258 break;
1261 if (wmip->wmi_is_wmm_enabled)
1263 break;
1265 pie += pie[1] + 2;
1268 A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
1269 ev->listenInterval, ev->beaconInterval,
1270 (NETWORK_TYPE) ev->networkType, ev->beaconIeLen,
1271 ev->assocReqLen, ev->assocRespLen,
1272 ev->assocInfo);
1274 return 0;
1277 static int
1278 wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1280 WMI_REG_DOMAIN_EVENT *ev;
1282 if (len < sizeof(*ev)) {
1283 return A_EINVAL;
1285 ev = (WMI_REG_DOMAIN_EVENT *)datap;
1287 A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
1289 return 0;
1292 static int
1293 wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1295 WMI_NEIGHBOR_REPORT_EVENT *ev;
1296 int numAps;
1298 if (len < sizeof(*ev)) {
1299 return A_EINVAL;
1301 ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
1302 numAps = ev->numberOfAps;
1304 if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
1305 return A_EINVAL;
1308 A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
1310 return 0;
1313 static int
1314 wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1316 WMI_DISCONNECT_EVENT *ev;
1317 wmip->wmi_traffic_class = 100;
1319 if (len < sizeof(WMI_DISCONNECT_EVENT)) {
1320 return A_EINVAL;
1322 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1324 ev = (WMI_DISCONNECT_EVENT *)datap;
1326 A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
1328 wmip->wmi_is_wmm_enabled = false;
1329 wmip->wmi_pair_crypto_type = NONE_CRYPT;
1330 wmip->wmi_grp_crypto_type = NONE_CRYPT;
1332 A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
1333 ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
1335 return 0;
1338 static int
1339 wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1341 WMI_PEER_NODE_EVENT *ev;
1343 if (len < sizeof(WMI_PEER_NODE_EVENT)) {
1344 return A_EINVAL;
1346 ev = (WMI_PEER_NODE_EVENT *)datap;
1347 if (ev->eventCode == PEER_NODE_JOIN_EVENT) {
1348 A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG));
1349 } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) {
1350 A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG));
1353 A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
1355 return 0;
1358 static int
1359 wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1361 WMI_TKIP_MICERR_EVENT *ev;
1363 if (len < sizeof(*ev)) {
1364 return A_EINVAL;
1366 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1368 ev = (WMI_TKIP_MICERR_EVENT *)datap;
1369 A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
1371 return 0;
1374 static int
1375 wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1377 bss_t *bss = NULL;
1378 WMI_BSS_INFO_HDR *bih;
1379 u8 *buf;
1380 u32 nodeCachingAllowed = 1;
1381 u8 cached_ssid_len = 0;
1382 u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
1383 u8 beacon_ssid_len = 0;
1385 if (len <= sizeof(WMI_BSS_INFO_HDR)) {
1386 return A_EINVAL;
1389 bih = (WMI_BSS_INFO_HDR *)datap;
1390 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1392 if (bih->rssi > 0) {
1393 if (NULL == bss)
1394 return 0; //no node found in the table, just drop the node with incorrect RSSI
1395 else
1396 bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
1399 A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
1400 /* What is driver config for wlan node caching? */
1401 if(ar6000_get_driver_cfg(wmip->wmi_devt,
1402 AR6000_DRIVER_CFG_GET_WLANNODECACHING,
1403 &nodeCachingAllowed) != 0) {
1404 wmi_node_return(wmip, bss);
1405 return A_EINVAL;
1408 if(!nodeCachingAllowed) {
1409 wmi_node_return(wmip, bss);
1410 return 0;
1413 buf = datap + sizeof(WMI_BSS_INFO_HDR);
1414 len -= sizeof(WMI_BSS_INFO_HDR);
1416 A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
1417 "bssid \"%pM\"\n", DBGARG, bih->channel,
1418 (unsigned char) bih->rssi, bih->bssid));
1420 if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
1421 wmi_node_return(wmip, bss);
1422 return 0;
1425 if (bss != NULL) {
1427 * Free up the node. Not the most efficient process given
1428 * we are about to allocate a new node but it is simple and should be
1429 * adequate.
1432 /* In case of hidden AP, beacon will not have ssid,
1433 * but a directed probe response will have it,
1434 * so cache the probe-resp-ssid if already present. */
1435 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
1437 u8 *ie_ssid;
1439 ie_ssid = bss->ni_cie.ie_ssid;
1440 if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
1442 cached_ssid_len = ie_ssid[1];
1443 memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len);
1448 * Use the current average rssi of associated AP base on assumpiton
1449 * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically
1450 * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...)
1451 * The average value of RSSI give end-user better feeling for instance value of scan result
1452 * It also sync up RSSI info in GUI between scan result and RSSI signal icon
1454 if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) {
1455 bih->rssi = bss->ni_rssi;
1456 bih->snr = bss->ni_snr;
1459 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1462 /* beacon/probe response frame format
1463 * [8] time stamp
1464 * [2] beacon interval
1465 * [2] capability information
1466 * [tlv] ssid */
1467 beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
1469 /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
1470 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1471 (0 != cached_ssid_len) &&
1472 (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1474 len += (cached_ssid_len - beacon_ssid_len);
1477 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1478 if (bss == NULL) {
1479 return A_NO_MEMORY;
1482 bss->ni_snr = bih->snr;
1483 bss->ni_rssi = bih->rssi;
1484 A_ASSERT(bss->ni_buf != NULL);
1486 /* In case of hidden AP, beacon will not have ssid,
1487 * but a directed probe response will have it,
1488 * so place the cached-ssid(probe-resp) in the bssinfo. */
1489 if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
1490 (0 != cached_ssid_len) &&
1491 (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
1493 u8 *ni_buf = bss->ni_buf;
1494 int buf_len = len;
1496 /* copy the first 14 bytes such as
1497 * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
1498 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
1500 ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
1501 ni_buf += (SSID_IE_LEN_INDEX + 1);
1503 buf += (SSID_IE_LEN_INDEX + 1);
1504 buf_len -= (SSID_IE_LEN_INDEX + 1);
1506 /* copy the cached ssid */
1507 memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
1508 ni_buf += cached_ssid_len;
1510 buf += beacon_ssid_len;
1511 buf_len -= beacon_ssid_len;
1513 if (cached_ssid_len > beacon_ssid_len)
1514 buf_len -= (cached_ssid_len - beacon_ssid_len);
1516 /* now copy the rest of bytes */
1517 memcpy(ni_buf, buf, buf_len);
1519 else
1520 memcpy(bss->ni_buf, buf, len);
1522 bss->ni_framelen = len;
1523 if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
1524 wlan_node_free(bss);
1525 return A_EINVAL;
1529 * Update the frequency in ie_chan, overwriting of channel number
1530 * which is done in wlan_parse_beacon
1532 bss->ni_cie.ie_chan = bih->channel;
1533 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1535 return 0;
1538 static int
1539 wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1541 bss_t *bss;
1542 WMI_OPT_RX_INFO_HDR *bih;
1543 u8 *buf;
1545 if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
1546 return A_EINVAL;
1549 bih = (WMI_OPT_RX_INFO_HDR *)datap;
1550 buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
1551 len -= sizeof(WMI_OPT_RX_INFO_HDR);
1553 A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
1554 bih->bssid[4], bih->bssid[5]));
1556 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
1557 if (bss != NULL) {
1559 * Free up the node. Not the most efficient process given
1560 * we are about to allocate a new node but it is simple and should be
1561 * adequate.
1563 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
1566 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
1567 if (bss == NULL) {
1568 return A_NO_MEMORY;
1571 bss->ni_snr = bih->snr;
1572 bss->ni_cie.ie_chan = bih->channel;
1573 A_ASSERT(bss->ni_buf != NULL);
1574 memcpy(bss->ni_buf, buf, len);
1575 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
1577 return 0;
1580 /* This event indicates inactivity timeout of a fatpipe(pstream)
1581 * at the target
1583 static int
1584 wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1586 WMI_PSTREAM_TIMEOUT_EVENT *ev;
1588 if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
1589 return A_EINVAL;
1592 A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
1594 ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
1596 /* When the pstream (fat pipe == AC) timesout, it means there were no
1597 * thinStreams within this pstream & it got implicitly created due to
1598 * data flow on this AC. We start the inactivity timer only for
1599 * implicitly created pstream. Just reset the host state.
1601 /* Set the activeTsids for this AC to 0 */
1602 LOCK_WMI(wmip);
1603 wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
1604 wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
1605 UNLOCK_WMI(wmip);
1607 /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
1608 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
1610 return 0;
1613 static int
1614 wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1616 WMI_BIT_RATE_REPLY *reply;
1617 s32 rate;
1618 u32 sgi,index;
1619 /* 54149:
1620 * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
1621 * since there is difference in the length and to avoid returning
1622 * error value.
1624 if (len < sizeof(WMI_BIT_RATE_REPLY)) {
1625 return A_EINVAL;
1627 reply = (WMI_BIT_RATE_REPLY *)datap;
1628 A_DPRINTF(DBG_WMI,
1629 (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
1631 if (reply->rateIndex == (s8) RATE_AUTO) {
1632 rate = RATE_AUTO;
1633 } else {
1634 // the SGI state is stored as the MSb of the rateIndex
1635 index = reply->rateIndex & 0x7f;
1636 sgi = (reply->rateIndex & 0x80)? 1:0;
1637 rate = wmi_rateTable[index][sgi];
1640 A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
1641 return 0;
1644 static int
1645 wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1647 WMI_FIX_RATES_REPLY *reply;
1649 if (len < sizeof(WMI_FIX_RATES_REPLY)) {
1650 return A_EINVAL;
1652 reply = (WMI_FIX_RATES_REPLY *)datap;
1653 A_DPRINTF(DBG_WMI,
1654 (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
1656 A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
1658 return 0;
1661 static int
1662 wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1664 WMI_CHANNEL_LIST_REPLY *reply;
1666 if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
1667 return A_EINVAL;
1669 reply = (WMI_CHANNEL_LIST_REPLY *)datap;
1670 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1672 A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
1673 reply->channelList);
1675 return 0;
1678 static int
1679 wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1681 WMI_TX_PWR_REPLY *reply;
1683 if (len < sizeof(*reply)) {
1684 return A_EINVAL;
1686 reply = (WMI_TX_PWR_REPLY *)datap;
1687 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1689 A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
1691 return 0;
1693 static int
1694 wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
1696 WMI_GET_KEEPALIVE_CMD *reply;
1698 if (len < sizeof(*reply)) {
1699 return A_EINVAL;
1701 reply = (WMI_GET_KEEPALIVE_CMD *)datap;
1702 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1704 A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
1706 return 0;
1710 static int
1711 wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1713 WMIX_DSETOPENREQ_EVENT *dsetopenreq;
1715 if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
1716 return A_EINVAL;
1718 dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
1719 A_DPRINTF(DBG_WMI,
1720 (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
1721 A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
1722 dsetopenreq->dset_id,
1723 dsetopenreq->targ_dset_handle,
1724 dsetopenreq->targ_reply_fn,
1725 dsetopenreq->targ_reply_arg);
1727 return 0;
1730 #ifdef CONFIG_HOST_DSET_SUPPORT
1731 static int
1732 wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
1734 WMIX_DSETCLOSE_EVENT *dsetclose;
1736 if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
1737 return A_EINVAL;
1739 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1741 dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
1742 A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
1744 return 0;
1747 static int
1748 wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
1750 WMIX_DSETDATAREQ_EVENT *dsetdatareq;
1752 if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
1753 return A_EINVAL;
1755 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1757 dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
1758 A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
1759 dsetdatareq->access_cookie,
1760 dsetdatareq->offset,
1761 dsetdatareq->length,
1762 dsetdatareq->targ_buf,
1763 dsetdatareq->targ_reply_fn,
1764 dsetdatareq->targ_reply_arg);
1766 return 0;
1768 #endif /* CONFIG_HOST_DSET_SUPPORT */
1770 static int
1771 wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
1773 WMI_SCAN_COMPLETE_EVENT *ev;
1775 ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1776 if ((int)ev->status == 0) {
1777 wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
1779 A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
1780 is_probe_ssid = false;
1782 return 0;
1786 * Target is reporting a programming error. This is for
1787 * developer aid only. Target only checks a few common violations
1788 * and it is responsibility of host to do all error checking.
1789 * Behavior of target after wmi error event is undefined.
1790 * A reset is recommended.
1792 static int
1793 wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1795 WMI_CMD_ERROR_EVENT *ev;
1797 ev = (WMI_CMD_ERROR_EVENT *)datap;
1798 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
1799 switch (ev->errorCode) {
1800 case (INVALID_PARAM):
1801 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
1802 break;
1803 case (ILLEGAL_STATE):
1804 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
1805 break;
1806 case (INTERNAL_ERROR):
1807 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
1808 break;
1811 return 0;
1815 static int
1816 wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1818 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1820 A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
1822 return 0;
1825 static int
1826 wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1828 WMI_RSSI_THRESHOLD_EVENT *reply;
1829 WMI_RSSI_THRESHOLD_VAL newThreshold;
1830 WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
1831 SQ_THRESHOLD_PARAMS *sq_thresh =
1832 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
1833 u8 upper_rssi_threshold, lower_rssi_threshold;
1834 s16 rssi;
1836 if (len < sizeof(*reply)) {
1837 return A_EINVAL;
1839 reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
1840 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1841 newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range;
1842 rssi = reply->rssi;
1845 * Identify the threshold breached and communicate that to the app. After
1846 * that install a new set of thresholds based on the signal quality
1847 * reported by the target
1849 if (newThreshold) {
1850 /* Upper threshold breached */
1851 if (rssi < sq_thresh->upper_threshold[0]) {
1852 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: "
1853 " %d\n", DBGARG, rssi));
1854 } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1855 (rssi >= sq_thresh->upper_threshold[0]))
1857 newThreshold = WMI_RSSI_THRESHOLD1_ABOVE;
1858 } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1859 (rssi >= sq_thresh->upper_threshold[1]))
1861 newThreshold = WMI_RSSI_THRESHOLD2_ABOVE;
1862 } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1863 (rssi >= sq_thresh->upper_threshold[2]))
1865 newThreshold = WMI_RSSI_THRESHOLD3_ABOVE;
1866 } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1867 (rssi >= sq_thresh->upper_threshold[3]))
1869 newThreshold = WMI_RSSI_THRESHOLD4_ABOVE;
1870 } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1871 (rssi >= sq_thresh->upper_threshold[4]))
1873 newThreshold = WMI_RSSI_THRESHOLD5_ABOVE;
1874 } else if (rssi >= sq_thresh->upper_threshold[5]) {
1875 newThreshold = WMI_RSSI_THRESHOLD6_ABOVE;
1877 } else {
1878 /* Lower threshold breached */
1879 if (rssi > sq_thresh->lower_threshold[0]) {
1880 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: "
1881 "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0]));
1882 } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1883 (rssi <= sq_thresh->lower_threshold[0]))
1885 newThreshold = WMI_RSSI_THRESHOLD6_BELOW;
1886 } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1887 (rssi <= sq_thresh->lower_threshold[1]))
1889 newThreshold = WMI_RSSI_THRESHOLD5_BELOW;
1890 } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1891 (rssi <= sq_thresh->lower_threshold[2]))
1893 newThreshold = WMI_RSSI_THRESHOLD4_BELOW;
1894 } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1895 (rssi <= sq_thresh->lower_threshold[3]))
1897 newThreshold = WMI_RSSI_THRESHOLD3_BELOW;
1898 } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1899 (rssi <= sq_thresh->lower_threshold[4]))
1901 newThreshold = WMI_RSSI_THRESHOLD2_BELOW;
1902 } else if (rssi <= sq_thresh->lower_threshold[5]) {
1903 newThreshold = WMI_RSSI_THRESHOLD1_BELOW;
1906 /* Calculate and install the next set of thresholds */
1907 lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh,
1908 sq_thresh->lower_threshold_valid_count);
1909 upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh,
1910 sq_thresh->upper_threshold_valid_count);
1911 /* Issue a wmi command to install the thresholds */
1912 cmd.thresholdAbove1_Val = upper_rssi_threshold;
1913 cmd.thresholdBelow1_Val = lower_rssi_threshold;
1914 cmd.weight = sq_thresh->weight;
1915 cmd.pollTime = sq_thresh->polling_interval;
1917 rssi_event_value = rssi;
1919 if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
1920 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
1921 DBGARG));
1924 A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
1926 return 0;
1930 static int
1931 wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
1933 WMI_TARGET_ERROR_REPORT_EVENT *reply;
1935 if (len < sizeof(*reply)) {
1936 return A_EINVAL;
1938 reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
1939 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1941 A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
1943 return 0;
1946 static int
1947 wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
1949 WMI_CAC_EVENT *reply;
1950 WMM_TSPEC_IE *tspec_ie;
1951 u16 activeTsids;
1953 if (len < sizeof(*reply)) {
1954 return A_EINVAL;
1956 reply = (WMI_CAC_EVENT *)datap;
1958 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1960 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1961 (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) {
1962 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1964 wmi_delete_pstream_cmd(wmip, reply->ac,
1965 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1967 else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1968 u8 i;
1970 /* following assumes that there is only one outstanding ADDTS request
1971 when this event is received */
1972 LOCK_WMI(wmip);
1973 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1974 UNLOCK_WMI(wmip);
1976 for (i = 0; i < sizeof(activeTsids) * 8; i++) {
1977 if ((activeTsids >> i) & 1) {
1978 break;
1981 if (i < (sizeof(activeTsids) * 8)) {
1982 wmi_delete_pstream_cmd(wmip, reply->ac, i);
1986 * Ev#72990: Clear active tsids and Add missing handling
1987 * for delete qos stream from AP
1989 else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1990 u8 tsid = 0;
1992 tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
1993 tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
1994 LOCK_WMI(wmip);
1995 wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid);
1996 activeTsids = wmip->wmi_streamExistsForAC[reply->ac];
1997 UNLOCK_WMI(wmip);
2000 /* Indicate stream inactivity to driver layer only if all tsids
2001 * within this AC are deleted.
2003 if (!activeTsids) {
2004 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac);
2005 wmip->wmi_fatPipeExists &= ~(1 << reply->ac);
2009 A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
2010 reply->cac_indication, reply->statusCode,
2011 reply->tspecSuggestion);
2013 return 0;
2016 static int
2017 wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2019 WMI_CHANNEL_CHANGE_EVENT *reply;
2021 if (len < sizeof(*reply)) {
2022 return A_EINVAL;
2024 reply = (WMI_CHANNEL_CHANGE_EVENT *)datap;
2025 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2027 A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
2028 reply->newChannel);
2030 return 0;
2033 static int
2034 wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
2036 WMIX_HB_CHALLENGE_RESP_EVENT *reply;
2038 if (len < sizeof(*reply)) {
2039 return A_EINVAL;
2041 reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
2042 A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
2044 A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
2046 return 0;
2049 static int
2050 wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2052 WMI_TARGET_ROAM_TBL *reply;
2054 if (len < sizeof(*reply)) {
2055 return A_EINVAL;
2057 reply = (WMI_TARGET_ROAM_TBL *)datap;
2058 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2060 A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
2062 return 0;
2065 static int
2066 wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2068 WMI_TARGET_ROAM_DATA *reply;
2070 if (len < sizeof(*reply)) {
2071 return A_EINVAL;
2073 reply = (WMI_TARGET_ROAM_DATA *)datap;
2074 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2076 A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
2078 return 0;
2081 static int
2082 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2084 if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
2085 return A_EINVAL;
2087 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2089 A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
2091 return 0;
2094 static int
2095 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2097 WMI_SNR_THRESHOLD_EVENT *reply;
2098 SQ_THRESHOLD_PARAMS *sq_thresh =
2099 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
2100 WMI_SNR_THRESHOLD_VAL newThreshold;
2101 WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
2102 u8 upper_snr_threshold, lower_snr_threshold;
2103 s16 snr;
2105 if (len < sizeof(*reply)) {
2106 return A_EINVAL;
2108 reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
2109 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2111 newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range;
2112 snr = reply->snr;
2114 * Identify the threshold breached and communicate that to the app. After
2115 * that install a new set of thresholds based on the signal quality
2116 * reported by the target
2118 if (newThreshold) {
2119 /* Upper threshold breached */
2120 if (snr < sq_thresh->upper_threshold[0]) {
2121 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: "
2122 "%d\n", DBGARG, snr));
2123 } else if ((snr < sq_thresh->upper_threshold[1]) &&
2124 (snr >= sq_thresh->upper_threshold[0]))
2126 newThreshold = WMI_SNR_THRESHOLD1_ABOVE;
2127 } else if ((snr < sq_thresh->upper_threshold[2]) &&
2128 (snr >= sq_thresh->upper_threshold[1]))
2130 newThreshold = WMI_SNR_THRESHOLD2_ABOVE;
2131 } else if ((snr < sq_thresh->upper_threshold[3]) &&
2132 (snr >= sq_thresh->upper_threshold[2]))
2134 newThreshold = WMI_SNR_THRESHOLD3_ABOVE;
2135 } else if (snr >= sq_thresh->upper_threshold[3]) {
2136 newThreshold = WMI_SNR_THRESHOLD4_ABOVE;
2138 } else {
2139 /* Lower threshold breached */
2140 if (snr > sq_thresh->lower_threshold[0]) {
2141 A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: "
2142 "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0]));
2143 } else if ((snr > sq_thresh->lower_threshold[1]) &&
2144 (snr <= sq_thresh->lower_threshold[0]))
2146 newThreshold = WMI_SNR_THRESHOLD4_BELOW;
2147 } else if ((snr > sq_thresh->lower_threshold[2]) &&
2148 (snr <= sq_thresh->lower_threshold[1]))
2150 newThreshold = WMI_SNR_THRESHOLD3_BELOW;
2151 } else if ((snr > sq_thresh->lower_threshold[3]) &&
2152 (snr <= sq_thresh->lower_threshold[2]))
2154 newThreshold = WMI_SNR_THRESHOLD2_BELOW;
2155 } else if (snr <= sq_thresh->lower_threshold[3]) {
2156 newThreshold = WMI_SNR_THRESHOLD1_BELOW;
2160 /* Calculate and install the next set of thresholds */
2161 lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh,
2162 sq_thresh->lower_threshold_valid_count);
2163 upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh,
2164 sq_thresh->upper_threshold_valid_count);
2166 /* Issue a wmi command to install the thresholds */
2167 cmd.thresholdAbove1_Val = upper_snr_threshold;
2168 cmd.thresholdBelow1_Val = lower_snr_threshold;
2169 cmd.weight = sq_thresh->weight;
2170 cmd.pollTime = sq_thresh->polling_interval;
2172 A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n"
2173 ,DBGARG, snr, newThreshold, lower_snr_threshold,
2174 upper_snr_threshold));
2176 snr_event_value = snr;
2178 if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
2179 A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
2180 DBGARG));
2182 A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
2184 return 0;
2187 static int
2188 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2190 WMI_LQ_THRESHOLD_EVENT *reply;
2192 if (len < sizeof(*reply)) {
2193 return A_EINVAL;
2195 reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
2196 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2198 A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt,
2199 (WMI_LQ_THRESHOLD_VAL) reply->range,
2200 reply->lq);
2202 return 0;
2205 static int
2206 wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
2208 u16 ap_info_entry_size;
2209 WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
2210 WMI_AP_INFO_V1 *ap_info_v1;
2211 u8 i;
2213 if (len < sizeof(WMI_APLIST_EVENT)) {
2214 return A_EINVAL;
2217 if (ev->apListVer == APLIST_VER1) {
2218 ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
2219 ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
2220 } else {
2221 return A_EINVAL;
2224 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
2225 if (len < (int)(sizeof(WMI_APLIST_EVENT) +
2226 (ev->numAP - 1) * ap_info_entry_size))
2228 return A_EINVAL;
2232 * AP List Ver1 Contents
2234 for (i = 0; i < ev->numAP; i++) {
2235 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
2236 "Channel %d\n", i,
2237 ap_info_v1->bssid[0], ap_info_v1->bssid[1],
2238 ap_info_v1->bssid[2], ap_info_v1->bssid[3],
2239 ap_info_v1->bssid[4], ap_info_v1->bssid[5],
2240 ap_info_v1->channel));
2241 ap_info_v1++;
2243 return 0;
2246 static int
2247 wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
2249 u32 dropped;
2251 dropped = *((u32 *)datap);
2252 datap += sizeof(dropped);
2253 len -= sizeof(dropped);
2254 A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
2255 return 0;
2259 * Called to send a wmi command. Command specific data is already built
2260 * on osbuf and current osbuf->data points to it.
2263 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
2264 WMI_SYNC_FLAG syncflag)
2266 int status;
2267 #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
2268 WMI_CMD_HDR *cHdr;
2269 HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id;
2271 A_ASSERT(osbuf != NULL);
2273 if (syncflag >= END_WMIFLAG) {
2274 A_NETBUF_FREE(osbuf);
2275 return A_EINVAL;
2278 if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2280 * We want to make sure all data currently queued is transmitted before
2281 * the cmd execution. Establish a new sync point.
2283 wmi_sync_point(wmip);
2286 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
2287 A_NETBUF_FREE(osbuf);
2288 return A_NO_MEMORY;
2291 cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
2292 cHdr->commandId = (u16) cmdId;
2293 cHdr->info1 = 0; // added for virtual interface
2296 * Only for OPT_TX_CMD, use BE endpoint.
2298 if (IS_OPT_TX_CMD(cmdId)) {
2299 if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
2300 A_NETBUF_FREE(osbuf);
2301 return status;
2303 eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE);
2305 A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid);
2307 if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
2309 * We want to make sure all new data queued waits for the command to
2310 * execute. Establish a new sync point.
2312 wmi_sync_point(wmip);
2314 return (0);
2315 #undef IS_OPT_TX_CMD
2319 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
2320 WMI_SYNC_FLAG syncflag)
2322 WMIX_CMD_HDR *cHdr;
2324 if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
2325 A_NETBUF_FREE(osbuf);
2326 return A_NO_MEMORY;
2329 cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
2330 cHdr->commandId = (u32) cmdId;
2332 return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
2336 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
2337 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
2338 CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
2339 CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
2340 int ssidLength, u8 *ssid,
2341 u8 *bssid, u16 channel, u32 ctrl_flags)
2343 void *osbuf;
2344 WMI_CONNECT_CMD *cc;
2345 wmip->wmi_traffic_class = 100;
2347 if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
2348 return A_EINVAL;
2350 if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
2351 return A_EINVAL;
2354 osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
2355 if (osbuf == NULL) {
2356 return A_NO_MEMORY;
2359 A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
2361 cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2362 A_MEMZERO(cc, sizeof(*cc));
2364 if (ssidLength)
2366 memcpy(cc->ssid, ssid, ssidLength);
2369 cc->ssidLength = ssidLength;
2370 cc->networkType = netType;
2371 cc->dot11AuthMode = dot11AuthMode;
2372 cc->authMode = authMode;
2373 cc->pairwiseCryptoType = pairwiseCrypto;
2374 cc->pairwiseCryptoLen = pairwiseCryptoLen;
2375 cc->groupCryptoType = groupCrypto;
2376 cc->groupCryptoLen = groupCryptoLen;
2377 cc->channel = channel;
2378 cc->ctrl_flags = ctrl_flags;
2380 if (bssid != NULL) {
2381 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2384 wmip->wmi_pair_crypto_type = pairwiseCrypto;
2385 wmip->wmi_grp_crypto_type = groupCrypto;
2387 return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
2391 wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
2393 void *osbuf;
2394 WMI_RECONNECT_CMD *cc;
2395 wmip->wmi_traffic_class = 100;
2397 osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
2398 if (osbuf == NULL) {
2399 return A_NO_MEMORY;
2402 A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
2404 cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
2405 A_MEMZERO(cc, sizeof(*cc));
2407 cc->channel = channel;
2409 if (bssid != NULL) {
2410 memcpy(cc->bssid, bssid, ATH_MAC_LEN);
2413 return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
2417 wmi_disconnect_cmd(struct wmi_t *wmip)
2419 int status;
2420 wmip->wmi_traffic_class = 100;
2422 /* Bug fix for 24817(elevator bug) - the disconnect command does not
2423 need to do a SYNC before.*/
2424 status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID);
2426 return status;
2430 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
2431 u32 forceFgScan, u32 isLegacy,
2432 u32 homeDwellTime, u32 forceScanInterval,
2433 s8 numChan, u16 *channelList)
2435 void *osbuf;
2436 WMI_START_SCAN_CMD *sc;
2437 s8 size;
2439 size = sizeof (*sc);
2441 if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
2442 return A_EINVAL;
2445 if (numChan) {
2446 if (numChan > WMI_MAX_CHANNELS) {
2447 return A_EINVAL;
2449 size += sizeof(u16) * (numChan - 1);
2452 osbuf = A_NETBUF_ALLOC(size);
2453 if (osbuf == NULL) {
2454 return A_NO_MEMORY;
2457 A_NETBUF_PUT(osbuf, size);
2459 sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
2460 sc->scanType = scanType;
2461 sc->forceFgScan = forceFgScan;
2462 sc->isLegacy = isLegacy;
2463 sc->homeDwellTime = homeDwellTime;
2464 sc->forceScanInterval = forceScanInterval;
2465 sc->numChannels = numChan;
2466 if (numChan) {
2467 memcpy(sc->channelList, channelList, numChan * sizeof(u16));
2470 return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
2474 wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
2475 u16 fg_end_sec, u16 bg_sec,
2476 u16 minact_chdw_msec, u16 maxact_chdw_msec,
2477 u16 pas_chdw_msec,
2478 u8 shScanRatio, u8 scanCtrlFlags,
2479 u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
2481 void *osbuf;
2482 WMI_SCAN_PARAMS_CMD *sc;
2484 osbuf = A_NETBUF_ALLOC(sizeof(*sc));
2485 if (osbuf == NULL) {
2486 return A_NO_MEMORY;
2489 A_NETBUF_PUT(osbuf, sizeof(*sc));
2491 sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2492 A_MEMZERO(sc, sizeof(*sc));
2493 sc->fg_start_period = fg_start_sec;
2494 sc->fg_end_period = fg_end_sec;
2495 sc->bg_period = bg_sec;
2496 sc->minact_chdwell_time = minact_chdw_msec;
2497 sc->maxact_chdwell_time = maxact_chdw_msec;
2498 sc->pas_chdwell_time = pas_chdw_msec;
2499 sc->shortScanRatio = shScanRatio;
2500 sc->scanCtrlFlags = scanCtrlFlags;
2501 sc->max_dfsch_act_time = max_dfsch_act_time;
2502 sc->maxact_scan_per_ssid = maxact_scan_per_ssid;
2504 return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
2505 NO_SYNC_WMIFLAG));
2509 wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
2511 void *osbuf;
2512 WMI_BSS_FILTER_CMD *cmd;
2514 if (filter >= LAST_BSS_FILTER) {
2515 return A_EINVAL;
2518 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2519 if (osbuf == NULL) {
2520 return A_NO_MEMORY;
2523 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2525 cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
2526 A_MEMZERO(cmd, sizeof(*cmd));
2527 cmd->bssFilter = filter;
2528 cmd->ieMask = ieMask;
2530 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
2531 NO_SYNC_WMIFLAG));
2535 wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
2536 u8 ssidLength, u8 *ssid)
2538 void *osbuf;
2539 WMI_PROBED_SSID_CMD *cmd;
2541 if (index > MAX_PROBED_SSID_INDEX) {
2542 return A_EINVAL;
2544 if (ssidLength > sizeof(cmd->ssid)) {
2545 return A_EINVAL;
2547 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
2548 return A_EINVAL;
2550 if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
2551 return A_EINVAL;
2554 if (flag & SPECIFIC_SSID_FLAG) {
2555 is_probe_ssid = true;
2558 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2559 if (osbuf == NULL) {
2560 return A_NO_MEMORY;
2563 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2565 cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
2566 A_MEMZERO(cmd, sizeof(*cmd));
2567 cmd->entryIndex = index;
2568 cmd->flag = flag;
2569 cmd->ssidLength = ssidLength;
2570 memcpy(cmd->ssid, ssid, ssidLength);
2572 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
2573 NO_SYNC_WMIFLAG));
2577 wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
2579 void *osbuf;
2580 WMI_LISTEN_INT_CMD *cmd;
2582 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2583 if (osbuf == NULL) {
2584 return A_NO_MEMORY;
2587 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2589 cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
2590 A_MEMZERO(cmd, sizeof(*cmd));
2591 cmd->listenInterval = listenInterval;
2592 cmd->numBeacons = listenBeacons;
2594 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
2595 NO_SYNC_WMIFLAG));
2599 wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
2601 void *osbuf;
2602 WMI_BMISS_TIME_CMD *cmd;
2604 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2605 if (osbuf == NULL) {
2606 return A_NO_MEMORY;
2609 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2611 cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
2612 A_MEMZERO(cmd, sizeof(*cmd));
2613 cmd->bmissTime = bmissTime;
2614 cmd->numBeacons = bmissBeacons;
2616 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
2617 NO_SYNC_WMIFLAG));
2621 wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
2622 u8 ieLen, u8 *ieInfo)
2624 void *osbuf;
2625 WMI_SET_ASSOC_INFO_CMD *cmd;
2626 u16 cmdLen;
2628 cmdLen = sizeof(*cmd) + ieLen - 1;
2629 osbuf = A_NETBUF_ALLOC(cmdLen);
2630 if (osbuf == NULL) {
2631 return A_NO_MEMORY;
2634 A_NETBUF_PUT(osbuf, cmdLen);
2636 cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
2637 A_MEMZERO(cmd, cmdLen);
2638 cmd->ieType = ieType;
2639 cmd->bufferSize = ieLen;
2640 memcpy(cmd->assocInfo, ieInfo, ieLen);
2642 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
2643 NO_SYNC_WMIFLAG));
2647 wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
2649 void *osbuf;
2650 WMI_POWER_MODE_CMD *cmd;
2652 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2653 if (osbuf == NULL) {
2654 return A_NO_MEMORY;
2657 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2659 cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2660 A_MEMZERO(cmd, sizeof(*cmd));
2661 cmd->powerMode = powerMode;
2662 wmip->wmi_powerMode = powerMode;
2664 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
2665 NO_SYNC_WMIFLAG));
2669 wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
2670 u16 atim_windows, u16 timeout_value)
2672 void *osbuf;
2673 WMI_IBSS_PM_CAPS_CMD *cmd;
2675 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2676 if (osbuf == NULL) {
2677 return A_NO_MEMORY;
2680 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2682 cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
2683 A_MEMZERO(cmd, sizeof(*cmd));
2684 cmd->power_saving = pmEnable;
2685 cmd->ttl = ttl;
2686 cmd->atim_windows = atim_windows;
2687 cmd->timeout_value = timeout_value;
2689 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
2690 NO_SYNC_WMIFLAG));
2694 wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
2695 u32 ps_period, u8 sleep_period)
2697 void *osbuf;
2698 WMI_AP_PS_CMD *cmd;
2700 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2701 if (osbuf == NULL) {
2702 return A_NO_MEMORY;
2705 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2707 cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf));
2708 A_MEMZERO(cmd, sizeof(*cmd));
2709 cmd->psType = psType;
2710 cmd->idle_time = idle_time;
2711 cmd->ps_period = ps_period;
2712 cmd->sleep_period = sleep_period;
2714 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID,
2715 NO_SYNC_WMIFLAG));
2719 wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
2720 u16 psPollNum, u16 dtimPolicy,
2721 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2722 u16 ps_fail_event_policy)
2724 void *osbuf;
2725 WMI_POWER_PARAMS_CMD *pm;
2727 osbuf = A_NETBUF_ALLOC(sizeof(*pm));
2728 if (osbuf == NULL) {
2729 return A_NO_MEMORY;
2732 A_NETBUF_PUT(osbuf, sizeof(*pm));
2734 pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2735 A_MEMZERO(pm, sizeof(*pm));
2736 pm->idle_period = idlePeriod;
2737 pm->pspoll_number = psPollNum;
2738 pm->dtim_policy = dtimPolicy;
2739 pm->tx_wakeup_policy = tx_wakeup_policy;
2740 pm->num_tx_to_wakeup = num_tx_to_wakeup;
2741 pm->ps_fail_event_policy = ps_fail_event_policy;
2743 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
2744 NO_SYNC_WMIFLAG));
2748 wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
2750 void *osbuf;
2751 WMI_DISC_TIMEOUT_CMD *cmd;
2753 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2754 if (osbuf == NULL) {
2755 return A_NO_MEMORY;
2758 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2760 cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
2761 A_MEMZERO(cmd, sizeof(*cmd));
2762 cmd->disconnectTimeout = timeout;
2764 return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
2765 NO_SYNC_WMIFLAG));
2769 wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
2770 u8 keyUsage, u8 keyLength, u8 *keyRSC,
2771 u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
2772 WMI_SYNC_FLAG sync_flag)
2774 void *osbuf;
2775 WMI_ADD_CIPHER_KEY_CMD *cmd;
2777 if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
2778 (keyMaterial == NULL))
2780 return A_EINVAL;
2783 if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
2784 return A_EINVAL;
2787 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2788 if (osbuf == NULL) {
2789 return A_NO_MEMORY;
2792 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2794 cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2795 A_MEMZERO(cmd, sizeof(*cmd));
2796 cmd->keyIndex = keyIndex;
2797 cmd->keyType = keyType;
2798 cmd->keyUsage = keyUsage;
2799 cmd->keyLength = keyLength;
2800 memcpy(cmd->key, keyMaterial, keyLength);
2801 #ifdef WAPI_ENABLE
2802 if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
2803 #else
2804 if (NULL != keyRSC) {
2805 #endif // WAPI_ENABLE
2806 memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
2808 cmd->key_op_ctrl = key_op_ctrl;
2810 if(macAddr) {
2811 memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
2814 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
2818 wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
2820 void *osbuf;
2821 WMI_ADD_KRK_CMD *cmd;
2823 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2824 if (osbuf == NULL) {
2825 return A_NO_MEMORY;
2828 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2830 cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
2831 A_MEMZERO(cmd, sizeof(*cmd));
2832 memcpy(cmd->krk, krk, WMI_KRK_LEN);
2834 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
2838 wmi_delete_krk_cmd(struct wmi_t *wmip)
2840 return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
2844 wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
2846 void *osbuf;
2847 WMI_DELETE_CIPHER_KEY_CMD *cmd;
2849 if (keyIndex > WMI_MAX_KEY_INDEX) {
2850 return A_EINVAL;
2853 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2854 if (osbuf == NULL) {
2855 return A_NO_MEMORY;
2858 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2860 cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
2861 A_MEMZERO(cmd, sizeof(*cmd));
2862 cmd->keyIndex = keyIndex;
2864 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
2865 NO_SYNC_WMIFLAG));
2869 wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
2870 bool set)
2872 void *osbuf;
2873 WMI_SET_PMKID_CMD *cmd;
2875 if (bssid == NULL) {
2876 return A_EINVAL;
2879 if ((set == true) && (pmkId == NULL)) {
2880 return A_EINVAL;
2883 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2884 if (osbuf == NULL) {
2885 return A_NO_MEMORY;
2888 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2890 cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
2891 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
2892 if (set == true) {
2893 memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
2894 cmd->enable = PMKID_ENABLE;
2895 } else {
2896 A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
2897 cmd->enable = PMKID_DISABLE;
2900 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
2904 wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
2906 void *osbuf;
2907 WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
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_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
2917 cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
2919 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
2920 NO_SYNC_WMIFLAG));
2924 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
2925 WMI_SET_AKMP_PARAMS_CMD *akmpParams)
2927 void *osbuf;
2928 WMI_SET_AKMP_PARAMS_CMD *cmd;
2930 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2931 if (osbuf == NULL) {
2932 return A_NO_MEMORY;
2935 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2936 cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2937 cmd->akmpInfo = akmpParams->akmpInfo;
2939 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
2940 NO_SYNC_WMIFLAG));
2944 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
2945 WMI_SET_PMKID_LIST_CMD *pmkInfo)
2947 void *osbuf;
2948 WMI_SET_PMKID_LIST_CMD *cmd;
2949 u16 cmdLen;
2950 u8 i;
2952 cmdLen = sizeof(pmkInfo->numPMKID) +
2953 pmkInfo->numPMKID * sizeof(WMI_PMKID);
2955 osbuf = A_NETBUF_ALLOC(cmdLen);
2956 if (osbuf == NULL) {
2957 return A_NO_MEMORY;
2960 A_NETBUF_PUT(osbuf, cmdLen);
2961 cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2962 cmd->numPMKID = pmkInfo->numPMKID;
2964 for (i = 0; i < cmd->numPMKID; i++) {
2965 memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
2966 WMI_PMKID_LEN);
2969 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
2970 NO_SYNC_WMIFLAG));
2974 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
2976 return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
2980 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
2982 WMI_DATA_HDR *dtHdr;
2984 A_ASSERT( eid != wmip->wmi_endpoint_id);
2985 A_ASSERT(osbuf != NULL);
2987 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
2988 return A_NO_MEMORY;
2991 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
2992 dtHdr->info =
2993 (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
2995 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid));
2997 return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid));
3000 typedef struct _WMI_DATA_SYNC_BUFS {
3001 u8 trafficClass;
3002 void *osbuf;
3003 }WMI_DATA_SYNC_BUFS;
3005 static int
3006 wmi_sync_point(struct wmi_t *wmip)
3008 void *cmd_osbuf;
3009 WMI_SYNC_CMD *cmd;
3010 WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
3011 u8 i,numPriStreams=0;
3012 int status = 0;
3014 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3016 memset(dataSyncBufs,0,sizeof(dataSyncBufs));
3018 /* lock out while we walk through the priority list and assemble our local array */
3019 LOCK_WMI(wmip);
3021 for (i=0; i < WMM_NUM_AC ; i++) {
3022 if (wmip->wmi_fatPipeExists & (1 << i)) {
3023 numPriStreams++;
3024 dataSyncBufs[numPriStreams-1].trafficClass = i;
3028 UNLOCK_WMI(wmip);
3030 /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
3032 do {
3034 * We allocate all network buffers needed so we will be able to
3035 * send all required frames.
3037 cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3038 if (cmd_osbuf == NULL) {
3039 status = A_NO_MEMORY;
3040 break;
3043 A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd));
3045 cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf));
3046 A_MEMZERO(cmd, sizeof(*cmd));
3048 /* In the SYNC cmd sent on the control Ep, send a bitmap of the data
3049 * eps on which the Data Sync will be sent
3051 cmd->dataSyncMap = wmip->wmi_fatPipeExists;
3053 for (i=0; i < numPriStreams ; i++) {
3054 dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
3055 if (dataSyncBufs[i].osbuf == NULL) {
3056 status = A_NO_MEMORY;
3057 break;
3059 } //end for
3061 /* if Buffer allocation for any of the dataSync fails, then do not
3062 * send the Synchronize cmd on the control ep
3064 if (status) {
3065 break;
3069 * Send sync cmd followed by sync data messages on all endpoints being
3070 * used
3072 status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
3073 NO_SYNC_WMIFLAG);
3075 if (status) {
3076 break;
3078 /* cmd buffer sent, we no longer own it */
3079 cmd_osbuf = NULL;
3081 for(i=0; i < numPriStreams; i++) {
3082 A_ASSERT(dataSyncBufs[i].osbuf != NULL);
3083 status = wmi_dataSync_send(wmip,
3084 dataSyncBufs[i].osbuf,
3085 A_WMI_Ac2EndpointID(wmip->wmi_devt,
3086 dataSyncBufs[i].
3087 trafficClass)
3090 if (status) {
3091 break;
3093 /* we don't own this buffer anymore, NULL it out of the array so it
3094 * won't get cleaned up */
3095 dataSyncBufs[i].osbuf = NULL;
3096 } //end for
3098 } while(false);
3100 /* free up any resources left over (possibly due to an error) */
3102 if (cmd_osbuf != NULL) {
3103 A_NETBUF_FREE(cmd_osbuf);
3106 for (i = 0; i < numPriStreams; i++) {
3107 if (dataSyncBufs[i].osbuf != NULL) {
3108 A_NETBUF_FREE(dataSyncBufs[i].osbuf);
3112 return (status);
3116 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
3118 void *osbuf;
3119 WMI_CREATE_PSTREAM_CMD *cmd;
3120 u8 fatPipeExistsForAC=0;
3121 s32 minimalPHY = 0;
3122 s32 nominalPHY = 0;
3124 /* Validate all the parameters. */
3125 if( !((params->userPriority < 8) &&
3126 (params->userPriority <= 0x7) &&
3127 (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
3128 (params->trafficDirection == UPLINK_TRAFFIC ||
3129 params->trafficDirection == DNLINK_TRAFFIC ||
3130 params->trafficDirection == BIDIR_TRAFFIC) &&
3131 (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
3132 params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
3133 (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
3134 params->voicePSCapability == ENABLE_FOR_THIS_AC ||
3135 params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
3136 (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
3138 return A_EINVAL;
3142 // check nominal PHY rate is >= minimalPHY, so that DUT
3143 // can allow TSRS IE
3146 // get the physical rate
3147 minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps
3149 // check minimal phy < nominal phy rate
3151 if (params->nominalPHY >= minimalPHY)
3153 nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps
3154 A_DPRINTF(DBG_WMI,
3155 (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG,
3156 minimalPHY, nominalPHY));
3158 params->nominalPHY = nominalPHY;
3160 else
3162 params->nominalPHY = 0;
3165 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3166 if (osbuf == NULL) {
3167 return A_NO_MEMORY;
3170 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3172 A_DPRINTF(DBG_WMI,
3173 (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
3174 params->trafficClass, params->tsid));
3176 cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3177 A_MEMZERO(cmd, sizeof(*cmd));
3178 memcpy(cmd, params, sizeof(*cmd));
3180 /* this is an implicitly created Fat pipe */
3181 if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
3182 LOCK_WMI(wmip);
3183 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3184 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3185 UNLOCK_WMI(wmip);
3186 } else {
3187 /* this is an explicitly created thin stream within a fat pipe */
3188 LOCK_WMI(wmip);
3189 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
3190 wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
3191 /* if a thinstream becomes active, the fat pipe automatically
3192 * becomes active
3194 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
3195 UNLOCK_WMI(wmip);
3198 /* Indicate activty change to driver layer only if this is the
3199 * first TSID to get created in this AC explicitly or an implicit
3200 * fat pipe is getting created.
3202 if (!fatPipeExistsForAC) {
3203 A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
3206 /* mike: should be SYNC_BEFORE_WMIFLAG */
3207 return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
3208 NO_SYNC_WMIFLAG));
3212 wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
3214 void *osbuf;
3215 WMI_DELETE_PSTREAM_CMD *cmd;
3216 int status;
3217 u16 activeTsids=0;
3219 /* validate the parameters */
3220 if (trafficClass > 3) {
3221 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass));
3222 return A_EINVAL;
3225 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3226 if (osbuf == NULL) {
3227 return A_NO_MEMORY;
3230 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3232 cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
3233 A_MEMZERO(cmd, sizeof(*cmd));
3235 cmd->trafficClass = trafficClass;
3236 cmd->tsid = tsid;
3238 LOCK_WMI(wmip);
3239 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3240 UNLOCK_WMI(wmip);
3242 /* Check if the tsid was created & exists */
3243 if (!(activeTsids & (1<<tsid))) {
3245 A_NETBUF_FREE(osbuf);
3246 A_DPRINTF(DBG_WMI,
3247 (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
3248 /* TODO: return a more appropriate err code */
3249 return A_ERROR;
3252 A_DPRINTF(DBG_WMI,
3253 (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
3255 status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
3256 SYNC_BEFORE_WMIFLAG));
3258 LOCK_WMI(wmip);
3259 wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
3260 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3261 UNLOCK_WMI(wmip);
3264 /* Indicate stream inactivity to driver layer only if all tsids
3265 * within this AC are deleted.
3267 if(!activeTsids) {
3268 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
3269 wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
3272 return status;
3276 wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
3278 void *osbuf;
3279 WMI_FRAME_RATES_CMD *cmd;
3280 u8 frameType;
3282 A_DPRINTF(DBG_WMI,
3283 (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
3285 if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) ||
3286 (subType > 15)){
3288 return A_EINVAL;
3291 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3292 if (osbuf == NULL) {
3293 return A_NO_MEMORY;
3296 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3298 cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3299 A_MEMZERO(cmd, sizeof(*cmd));
3301 frameType = (u8)((subType << 4) | type);
3303 cmd->bEnableMask = bEnable;
3304 cmd->frameType = frameType;
3305 cmd->frameRateMask = rateMask;
3307 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG));
3311 * used to set the bit rate. rate is in Kbps. If rate == -1
3312 * then auto selection is used.
3315 wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
3317 void *osbuf;
3318 WMI_BIT_RATE_CMD *cmd;
3319 s8 drix, mrix, crix, ret_val;
3321 if (dataRate != -1) {
3322 ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
3323 if(ret_val == A_EINVAL){
3324 return A_EINVAL;
3326 } else {
3327 drix = -1;
3330 if (mgmtRate != -1) {
3331 ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix);
3332 if(ret_val == A_EINVAL){
3333 return A_EINVAL;
3335 } else {
3336 mrix = -1;
3338 if (ctlRate != -1) {
3339 ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix);
3340 if(ret_val == A_EINVAL){
3341 return A_EINVAL;
3343 } else {
3344 crix = -1;
3346 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3347 if (osbuf == NULL) {
3348 return A_NO_MEMORY;
3351 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3353 cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
3354 A_MEMZERO(cmd, sizeof(*cmd));
3356 cmd->rateIndex = drix;
3357 cmd->mgmtRateIndex = mrix;
3358 cmd->ctlRateIndex = crix;
3361 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
3365 wmi_get_bitrate_cmd(struct wmi_t *wmip)
3367 return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
3371 * Returns true iff the given rate index is legal in the current PHY mode.
3373 bool
3374 wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
3376 WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
3377 bool isValid = true;
3378 switch(phyMode) {
3379 case WMI_11A_MODE:
3380 if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
3381 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3382 isValid = false;
3384 } else {
3385 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
3386 isValid = false;
3389 break;
3391 case WMI_11B_MODE:
3392 if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
3393 isValid = false;
3395 break;
3397 case WMI_11GONLY_MODE:
3398 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3399 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3400 isValid = false;
3402 } else {
3403 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
3404 isValid = false;
3407 break;
3409 case WMI_11G_MODE:
3410 case WMI_11AG_MODE:
3411 if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
3412 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
3413 isValid = false;
3415 } else {
3416 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
3417 isValid = false;
3420 break;
3421 default:
3422 A_ASSERT(false);
3423 break;
3426 return isValid;
3429 s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
3431 s8 i;
3433 for (i=0;;i++)
3435 if (wmi_rateTable[(u32) i][0] == 0) {
3436 return A_EINVAL;
3438 if (wmi_rateTable[(u32) i][0] == rate) {
3439 break;
3443 if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
3444 return A_EINVAL;
3447 *rate_idx = i;
3448 return 0;
3452 wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
3454 void *osbuf;
3455 WMI_FIX_RATES_CMD *cmd;
3456 #if 0
3457 s32 rateIndex;
3458 /* This check does not work for AR6003 as the HT modes are enabled only when
3459 * the STA is connected to a HT_BSS and is not based only on channel. It is
3460 * safe to skip this check however because rate control will only use rates
3461 * that are permitted by the valid rate mask and the fix rate mask. Meaning
3462 * the fix rate mask is not sufficient by itself to cause an invalid rate
3463 * to be used. */
3464 /* Make sure all rates in the mask are valid in the current PHY mode */
3465 for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
3466 if((1 << rateIndex) & (u32)fixRatesMask) {
3467 if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
3468 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
3469 return A_EINVAL;
3473 #endif
3476 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3477 if (osbuf == NULL) {
3478 return A_NO_MEMORY;
3481 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3483 cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
3484 A_MEMZERO(cmd, sizeof(*cmd));
3486 cmd->fixRateMask = fixRatesMask;
3488 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
3492 wmi_get_ratemask_cmd(struct wmi_t *wmip)
3494 return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
3498 wmi_get_channelList_cmd(struct wmi_t *wmip)
3500 return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
3504 * used to generate a wmi sey channel Parameters cmd.
3505 * mode should always be specified and corresponds to the phy mode of the
3506 * wlan.
3507 * numChan should alway sbe specified. If zero indicates that all available
3508 * channels should be used.
3509 * channelList is an array of channel frequencies (in Mhz) which the radio
3510 * should limit its operation to. It should be NULL if numChan == 0. Size of
3511 * array should correspond to numChan entries.
3514 wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
3515 WMI_PHY_MODE mode, s8 numChan,
3516 u16 *channelList)
3518 void *osbuf;
3519 WMI_CHANNEL_PARAMS_CMD *cmd;
3520 s8 size;
3522 size = sizeof (*cmd);
3524 if (numChan) {
3525 if (numChan > WMI_MAX_CHANNELS) {
3526 return A_EINVAL;
3528 size += sizeof(u16) * (numChan - 1);
3531 osbuf = A_NETBUF_ALLOC(size);
3532 if (osbuf == NULL) {
3533 return A_NO_MEMORY;
3536 A_NETBUF_PUT(osbuf, size);
3538 cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3539 A_MEMZERO(cmd, size);
3541 wmip->wmi_phyMode = mode;
3542 cmd->scanParam = scanParam;
3543 cmd->phyMode = mode;
3544 cmd->numChannels = numChan;
3545 memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
3547 return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
3548 NO_SYNC_WMIFLAG));
3551 void
3552 wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3554 SQ_THRESHOLD_PARAMS *sq_thresh =
3555 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
3557 * Parse the command and store the threshold values here. The checks
3558 * for valid values can be put here
3560 sq_thresh->weight = rssiCmd->weight;
3561 sq_thresh->polling_interval = rssiCmd->pollTime;
3563 sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3564 sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3565 sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3566 sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3567 sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3568 sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3569 sq_thresh->upper_threshold_valid_count = 6;
3571 /* List sorted in descending order */
3572 sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3573 sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3574 sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3575 sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3576 sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3577 sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR;
3578 sq_thresh->lower_threshold_valid_count = 6;
3580 if (!rssi_event_value) {
3582 * Configuring the thresholds to their extremes allows the host to get an
3583 * event from the target which is used for the configuring the correct
3584 * thresholds
3586 rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0];
3587 rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0];
3588 } else {
3590 * In case the user issues multiple times of rssi_threshold_setting,
3591 * we should not use the extreames anymore, the target does not expect that.
3593 rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh,
3594 sq_thresh->upper_threshold_valid_count);
3595 rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh,
3596 sq_thresh->lower_threshold_valid_count);
3601 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
3602 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
3605 /* Check these values are in ascending order */
3606 if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
3607 rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
3608 rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
3609 rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
3610 rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
3611 rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
3612 rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
3613 rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
3614 rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
3615 rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val)
3617 return A_EINVAL;
3620 wmi_cache_configure_rssithreshold(wmip, rssiCmd);
3622 return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
3626 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
3628 void *osbuf;
3629 WMI_SET_IP_CMD *cmd;
3631 /* Multicast address are not valid */
3632 if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
3633 (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
3634 return A_EINVAL;
3637 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD));
3638 if (osbuf == NULL) {
3639 return A_NO_MEMORY;
3642 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
3643 cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
3644 memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
3646 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
3647 NO_SYNC_WMIFLAG));
3651 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
3652 WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
3654 void *osbuf;
3655 s8 size;
3656 WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
3657 u16 activeTsids=0;
3658 u8 streamExists=0;
3659 u8 i;
3661 if( hostModeCmd->awake == hostModeCmd->asleep) {
3662 return A_EINVAL;
3665 size = sizeof (*cmd);
3667 osbuf = A_NETBUF_ALLOC(size);
3668 if (osbuf == NULL) {
3669 return A_NO_MEMORY;
3672 A_NETBUF_PUT(osbuf, size);
3674 cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3675 A_MEMZERO(cmd, size);
3676 memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
3678 if(hostModeCmd->asleep) {
3680 * Relinquish credits from all implicitly created pstreams since when we
3681 * go to sleep. If user created explicit thinstreams exists with in a
3682 * fatpipe leave them intact for the user to delete
3684 LOCK_WMI(wmip);
3685 streamExists = wmip->wmi_fatPipeExists;
3686 UNLOCK_WMI(wmip);
3688 for(i=0;i< WMM_NUM_AC;i++) {
3689 if (streamExists & (1<<i)) {
3690 LOCK_WMI(wmip);
3691 activeTsids = wmip->wmi_streamExistsForAC[i];
3692 UNLOCK_WMI(wmip);
3693 /* If there are no user created thin streams delete the fatpipe */
3694 if(!activeTsids) {
3695 streamExists &= ~(1<<i);
3696 /*Indicate inactivity to drv layer for this fatpipe(pstream)*/
3697 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i);
3702 /* Update the fatpipes that exists*/
3703 LOCK_WMI(wmip);
3704 wmip->wmi_fatPipeExists = streamExists;
3705 UNLOCK_WMI(wmip);
3708 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
3709 NO_SYNC_WMIFLAG));
3713 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
3714 WMI_SET_WOW_MODE_CMD *wowModeCmd)
3716 void *osbuf;
3717 s8 size;
3718 WMI_SET_WOW_MODE_CMD *cmd;
3720 size = sizeof (*cmd);
3722 osbuf = A_NETBUF_ALLOC(size);
3723 if (osbuf == NULL) {
3724 return A_NO_MEMORY;
3727 A_NETBUF_PUT(osbuf, size);
3729 cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3730 A_MEMZERO(cmd, size);
3731 memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
3733 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
3734 NO_SYNC_WMIFLAG));
3739 wmi_get_wow_list_cmd(struct wmi_t *wmip,
3740 WMI_GET_WOW_LIST_CMD *wowListCmd)
3742 void *osbuf;
3743 s8 size;
3744 WMI_GET_WOW_LIST_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_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
3756 A_MEMZERO(cmd, size);
3757 memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
3759 return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
3760 NO_SYNC_WMIFLAG));
3764 static int
3765 wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
3767 WMI_GET_WOW_LIST_REPLY *reply;
3769 if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
3770 return A_EINVAL;
3772 reply = (WMI_GET_WOW_LIST_REPLY *)datap;
3774 A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
3775 reply);
3777 return 0;
3780 int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
3781 WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
3782 u8 *pattern, u8 *mask,
3783 u8 pattern_size)
3785 void *osbuf;
3786 s8 size;
3787 WMI_ADD_WOW_PATTERN_CMD *cmd;
3788 u8 *filter_mask = NULL;
3790 size = sizeof (*cmd);
3792 size += ((2 * addWowCmd->filter_size)* sizeof(u8));
3793 osbuf = A_NETBUF_ALLOC(size);
3794 if (osbuf == NULL) {
3795 return A_NO_MEMORY;
3798 A_NETBUF_PUT(osbuf, size);
3800 cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3801 cmd->filter_list_id = addWowCmd->filter_list_id;
3802 cmd->filter_offset = addWowCmd->filter_offset;
3803 cmd->filter_size = addWowCmd->filter_size;
3805 memcpy(cmd->filter, pattern, addWowCmd->filter_size);
3807 filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
3808 memcpy(filter_mask, mask, addWowCmd->filter_size);
3811 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
3812 NO_SYNC_WMIFLAG));
3816 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
3817 WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
3819 void *osbuf;
3820 s8 size;
3821 WMI_DEL_WOW_PATTERN_CMD *cmd;
3823 size = sizeof (*cmd);
3825 osbuf = A_NETBUF_ALLOC(size);
3826 if (osbuf == NULL) {
3827 return A_NO_MEMORY;
3830 A_NETBUF_PUT(osbuf, size);
3832 cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
3833 A_MEMZERO(cmd, size);
3834 memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
3836 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
3837 NO_SYNC_WMIFLAG));
3841 void
3842 wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3844 SQ_THRESHOLD_PARAMS *sq_thresh =
3845 &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
3847 * Parse the command and store the threshold values here. The checks
3848 * for valid values can be put here
3850 sq_thresh->weight = snrCmd->weight;
3851 sq_thresh->polling_interval = snrCmd->pollTime;
3853 sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val;
3854 sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val;
3855 sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val;
3856 sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val;
3857 sq_thresh->upper_threshold_valid_count = 4;
3859 /* List sorted in descending order */
3860 sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val;
3861 sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val;
3862 sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val;
3863 sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val;
3864 sq_thresh->lower_threshold_valid_count = 4;
3866 if (!snr_event_value) {
3868 * Configuring the thresholds to their extremes allows the host to get an
3869 * event from the target which is used for the configuring the correct
3870 * thresholds
3872 snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
3873 snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
3874 } else {
3876 * In case the user issues multiple times of snr_threshold_setting,
3877 * we should not use the extreames anymore, the target does not expect that.
3879 snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh,
3880 sq_thresh->upper_threshold_valid_count);
3881 snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh,
3882 sq_thresh->lower_threshold_valid_count);
3887 wmi_set_snr_threshold_params(struct wmi_t *wmip,
3888 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
3890 if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
3891 snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
3892 snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
3893 snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
3894 snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
3895 snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val)
3897 return A_EINVAL;
3899 wmi_cache_configure_snrthreshold(wmip, snrCmd);
3900 return (wmi_send_snr_threshold_params(wmip, snrCmd));
3904 wmi_clr_rssi_snr(struct wmi_t *wmip)
3906 void *osbuf;
3908 osbuf = A_NETBUF_ALLOC(sizeof(int));
3909 if (osbuf == NULL) {
3910 return A_NO_MEMORY;
3913 return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
3914 NO_SYNC_WMIFLAG));
3918 wmi_set_lq_threshold_params(struct wmi_t *wmip,
3919 WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
3921 void *osbuf;
3922 s8 size;
3923 WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
3924 /* These values are in ascending order */
3925 if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
3926 lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
3927 lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
3928 lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
3929 lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
3930 lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
3932 return A_EINVAL;
3935 size = sizeof (*cmd);
3937 osbuf = A_NETBUF_ALLOC(size);
3938 if (osbuf == NULL) {
3939 return A_NO_MEMORY;
3942 A_NETBUF_PUT(osbuf, size);
3944 cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3945 A_MEMZERO(cmd, size);
3946 memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
3948 return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
3949 NO_SYNC_WMIFLAG));
3953 wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
3955 void *osbuf;
3956 s8 size;
3957 WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
3959 size = sizeof (*cmd);
3961 osbuf = A_NETBUF_ALLOC(size);
3962 if (osbuf == NULL) {
3963 return A_NO_MEMORY;
3966 A_NETBUF_PUT(osbuf, size);
3968 cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
3969 A_MEMZERO(cmd, size);
3971 cmd->bitmask = mask;
3973 return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
3974 NO_SYNC_WMIFLAG));
3978 wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
3980 void *osbuf;
3981 WMIX_HB_CHALLENGE_RESP_CMD *cmd;
3983 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3984 if (osbuf == NULL) {
3985 return A_NO_MEMORY;
3988 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3990 cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
3991 cmd->cookie = cookie;
3992 cmd->source = source;
3994 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
3995 NO_SYNC_WMIFLAG));
3999 wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
4000 u16 tsr, bool rep, u16 size,
4001 u32 valid)
4003 void *osbuf;
4004 WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
4006 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4007 if (osbuf == NULL) {
4008 return A_NO_MEMORY;
4011 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4013 cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
4014 cmd->config.cfgmmask = mmask;
4015 cmd->config.cfgtsr = tsr;
4016 cmd->config.cfgrep = rep;
4017 cmd->config.cfgsize = size;
4018 cmd->config.cfgvalid = valid;
4020 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
4021 NO_SYNC_WMIFLAG));
4025 wmi_get_stats_cmd(struct wmi_t *wmip)
4027 return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
4031 wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
4033 void *osbuf;
4034 WMI_ADD_BAD_AP_CMD *cmd;
4036 if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
4037 return A_EINVAL;
4040 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4041 if (osbuf == NULL) {
4042 return A_NO_MEMORY;
4045 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4047 cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4048 cmd->badApIndex = apIndex;
4049 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4051 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
4055 wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
4057 void *osbuf;
4058 WMI_DELETE_BAD_AP_CMD *cmd;
4060 if (apIndex > WMI_MAX_BAD_AP_INDEX) {
4061 return A_EINVAL;
4064 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4065 if (osbuf == NULL) {
4066 return A_NO_MEMORY;
4069 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4071 cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
4072 cmd->badApIndex = apIndex;
4074 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
4075 NO_SYNC_WMIFLAG));
4079 wmi_abort_scan_cmd(struct wmi_t *wmip)
4081 return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
4085 wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
4087 void *osbuf;
4088 WMI_SET_TX_PWR_CMD *cmd;
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_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
4098 cmd->dbM = dbM;
4100 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
4104 wmi_get_txPwr_cmd(struct wmi_t *wmip)
4106 return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
4109 u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
4111 u16 activeTsids=0;
4113 LOCK_WMI(wmip);
4114 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
4115 UNLOCK_WMI(wmip);
4117 return activeTsids;
4121 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
4123 return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
4127 wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
4129 void *osbuf;
4130 u32 size = sizeof(u8);
4131 WMI_TARGET_ROAM_DATA *cmd;
4133 osbuf = A_NETBUF_ALLOC(size); /* no payload */
4134 if (osbuf == NULL) {
4135 return A_NO_MEMORY;
4138 A_NETBUF_PUT(osbuf, size);
4140 cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
4141 cmd->roamDataType = roamDataType;
4143 return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
4144 NO_SYNC_WMIFLAG));
4148 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
4149 u8 size)
4151 void *osbuf;
4152 WMI_SET_ROAM_CTRL_CMD *cmd;
4154 osbuf = A_NETBUF_ALLOC(size);
4155 if (osbuf == NULL) {
4156 return A_NO_MEMORY;
4159 A_NETBUF_PUT(osbuf, size);
4161 cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
4162 A_MEMZERO(cmd, size);
4164 memcpy(cmd, p, size);
4166 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
4167 NO_SYNC_WMIFLAG));
4171 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
4172 WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
4173 u8 size)
4175 void *osbuf;
4176 WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
4178 /* These timers can't be zero */
4179 if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
4180 !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
4181 pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
4182 !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
4183 pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
4184 return A_EINVAL;
4186 osbuf = A_NETBUF_ALLOC(size);
4187 if (osbuf == NULL) {
4188 return A_NO_MEMORY;
4191 A_NETBUF_PUT(osbuf, size);
4193 cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
4194 A_MEMZERO(cmd, size);
4196 memcpy(cmd, pCmd, size);
4198 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
4199 NO_SYNC_WMIFLAG));
4203 wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin,
4204 u8 eCWmax, u8 aifsn)
4206 void *osbuf;
4207 WMI_SET_ACCESS_PARAMS_CMD *cmd;
4209 if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
4210 (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC))
4212 return A_EINVAL;
4215 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4216 if (osbuf == NULL) {
4217 return A_NO_MEMORY;
4220 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4222 cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4223 cmd->txop = txop;
4224 cmd->eCWmin = eCWmin;
4225 cmd->eCWmax = eCWmax;
4226 cmd->aifsn = aifsn;
4227 cmd->ac = ac;
4229 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
4230 NO_SYNC_WMIFLAG));
4234 wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
4235 u8 trafficClass, u8 maxRetries,
4236 u8 enableNotify)
4238 void *osbuf;
4239 WMI_SET_RETRY_LIMITS_CMD *cmd;
4241 if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
4242 (frameType != DATA_FRAMETYPE))
4244 return A_EINVAL;
4247 if (maxRetries > WMI_MAX_RETRIES) {
4248 return A_EINVAL;
4251 if (frameType != DATA_FRAMETYPE) {
4252 trafficClass = 0;
4255 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4256 if (osbuf == NULL) {
4257 return A_NO_MEMORY;
4260 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4262 cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
4263 cmd->frameType = frameType;
4264 cmd->trafficClass = trafficClass;
4265 cmd->maxRetries = maxRetries;
4266 cmd->enableNotify = enableNotify;
4268 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
4269 NO_SYNC_WMIFLAG));
4272 void
4273 wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
4275 if (bssid != NULL) {
4276 memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
4281 wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
4283 void *osbuf;
4284 WMI_SET_OPT_MODE_CMD *cmd;
4286 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4287 if (osbuf == NULL) {
4288 return A_NO_MEMORY;
4291 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4293 cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4294 A_MEMZERO(cmd, sizeof(*cmd));
4295 cmd->optMode = optMode;
4297 return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
4298 SYNC_BOTH_WMIFLAG));
4302 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
4303 u8 frmType,
4304 u8 *dstMacAddr,
4305 u8 *bssid,
4306 u16 optIEDataLen,
4307 u8 *optIEData)
4309 void *osbuf;
4310 WMI_OPT_TX_FRAME_CMD *cmd;
4311 osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
4312 if (osbuf == NULL) {
4313 return A_NO_MEMORY;
4316 A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
4318 cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
4319 A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
4321 cmd->frmType = frmType;
4322 cmd->optIEDataLen = optIEDataLen;
4323 //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd));
4324 memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
4325 memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
4326 memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
4328 return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
4329 NO_SYNC_WMIFLAG));
4333 wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
4335 void *osbuf;
4336 WMI_BEACON_INT_CMD *cmd;
4338 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4339 if (osbuf == NULL) {
4340 return A_NO_MEMORY;
4343 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4345 cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
4346 A_MEMZERO(cmd, sizeof(*cmd));
4347 cmd->beaconInterval = intvl;
4349 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
4350 NO_SYNC_WMIFLAG));
4355 wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
4357 void *osbuf;
4358 WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
4360 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4361 if (osbuf == NULL) {
4362 return A_NO_MEMORY;
4365 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4367 cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
4368 A_MEMZERO(cmd, sizeof(*cmd));
4369 cmd->voicePktSize = voicePktSize;
4371 return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
4372 NO_SYNC_WMIFLAG));
4377 wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
4379 void *osbuf;
4380 WMI_SET_MAX_SP_LEN_CMD *cmd;
4382 /* maxSPLen is a two-bit value. If user trys to set anything
4383 * other than this, then its invalid
4385 if(maxSPLen & ~0x03)
4386 return A_EINVAL;
4388 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4389 if (osbuf == NULL) {
4390 return A_NO_MEMORY;
4393 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4395 cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
4396 A_MEMZERO(cmd, sizeof(*cmd));
4397 cmd->maxSPLen = maxSPLen;
4399 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
4400 NO_SYNC_WMIFLAG));
4403 u8 wmi_determine_userPriority(
4404 u8 *pkt,
4405 u32 layer2Pri)
4407 u8 ipPri;
4408 iphdr *ipHdr = (iphdr *)pkt;
4410 /* Determine IPTOS priority */
4412 * IP Tos format :
4413 * (Refer Pg 57 WMM-test-plan-v1.2)
4414 * IP-TOS - 8bits
4415 * : DSCP(6-bits) ECN(2-bits)
4416 * : DSCP - P2 P1 P0 X X X
4417 * where (P2 P1 P0) form 802.1D
4419 ipPri = ipHdr->ip_tos >> 5;
4420 ipPri &= 0x7;
4422 if ((layer2Pri & 0x7) > ipPri)
4423 return ((u8)layer2Pri & 0x7);
4424 else
4425 return ipPri;
4428 u8 convert_userPriority_to_trafficClass(u8 userPriority)
4430 return (up_to_ac[userPriority & 0x7]);
4433 u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
4435 return wmip->wmi_powerMode;
4439 wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
4441 int ret = 0;
4443 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
4444 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0
4445 #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0
4446 #define TSPEC_DELAY_BOUND_ATHEROS_DEF 0
4447 #define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0
4448 #define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */
4450 /* Verify TSPEC params for ATHEROS compliance */
4451 if(tspecCompliance == ATHEROS_COMPLIANCE) {
4452 if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) ||
4453 (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) ||
4454 (pCmd->minDataRate != pCmd->meanDataRate) ||
4455 (pCmd->minDataRate != pCmd->peakDataRate) ||
4456 (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) ||
4457 (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) ||
4458 (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) ||
4459 (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) {
4461 A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG));
4462 //A_PRINTF("%s: Invalid TSPEC params\n", __func__);
4463 ret = A_EINVAL;
4467 return ret;
4470 #ifdef CONFIG_HOST_TCMD_SUPPORT
4471 static int
4472 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
4475 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4477 return 0;
4480 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
4483 wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
4485 void *osbuf;
4486 WMI_SET_AUTH_MODE_CMD *cmd;
4488 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4489 if (osbuf == NULL) {
4490 return A_NO_MEMORY;
4493 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4495 cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4496 A_MEMZERO(cmd, sizeof(*cmd));
4497 cmd->mode = mode;
4499 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
4500 NO_SYNC_WMIFLAG));
4504 wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
4506 void *osbuf;
4507 WMI_SET_REASSOC_MODE_CMD *cmd;
4509 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4510 if (osbuf == NULL) {
4511 return A_NO_MEMORY;
4514 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4516 cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
4517 A_MEMZERO(cmd, sizeof(*cmd));
4518 cmd->mode = mode;
4520 return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
4521 NO_SYNC_WMIFLAG));
4525 wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
4527 void *osbuf;
4528 WMI_SET_LPREAMBLE_CMD *cmd;
4530 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4531 if (osbuf == NULL) {
4532 return A_NO_MEMORY;
4535 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4537 cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
4538 A_MEMZERO(cmd, sizeof(*cmd));
4539 cmd->status = status;
4540 cmd->preamblePolicy = preamblePolicy;
4542 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
4543 NO_SYNC_WMIFLAG));
4547 wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
4549 void *osbuf;
4550 WMI_SET_RTS_CMD *cmd;
4552 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4553 if (osbuf == NULL) {
4554 return A_NO_MEMORY;
4557 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4559 cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
4560 A_MEMZERO(cmd, sizeof(*cmd));
4561 cmd->threshold = threshold;
4563 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
4564 NO_SYNC_WMIFLAG));
4568 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
4570 void *osbuf;
4571 WMI_SET_WMM_CMD *cmd;
4573 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4574 if (osbuf == NULL) {
4575 return A_NO_MEMORY;
4578 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4580 cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
4581 A_MEMZERO(cmd, sizeof(*cmd));
4582 cmd->status = status;
4584 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
4585 NO_SYNC_WMIFLAG));
4590 wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
4592 void *osbuf;
4593 WMI_SET_QOS_SUPP_CMD *cmd;
4595 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4596 if (osbuf == NULL) {
4597 return A_NO_MEMORY;
4600 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4602 cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf));
4603 A_MEMZERO(cmd, sizeof(*cmd));
4604 cmd->status = status;
4605 return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID,
4606 NO_SYNC_WMIFLAG));
4611 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
4613 void *osbuf;
4614 WMI_SET_WMM_TXOP_CMD *cmd;
4616 if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
4617 return A_EINVAL;
4619 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4620 if (osbuf == NULL) {
4621 return A_NO_MEMORY;
4624 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4626 cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
4627 A_MEMZERO(cmd, sizeof(*cmd));
4628 cmd->txopEnable = cfg;
4630 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
4631 NO_SYNC_WMIFLAG));
4636 wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
4638 void *osbuf;
4639 WMI_AP_SET_COUNTRY_CMD *cmd;
4641 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4642 if (osbuf == NULL) {
4643 return A_NO_MEMORY;
4646 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4648 cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
4649 A_MEMZERO(cmd, sizeof(*cmd));
4650 memcpy(cmd->countryCode,countryCode,3);
4652 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
4653 NO_SYNC_WMIFLAG));
4656 #ifdef CONFIG_HOST_TCMD_SUPPORT
4657 /* WMI layer doesn't need to know the data type of the test cmd.
4658 This would be beneficial for customers like Qualcomm, who might
4659 have different test command requirements from different manufacturers
4662 wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
4664 void *osbuf;
4665 char *data;
4667 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
4669 osbuf= A_NETBUF_ALLOC(len);
4670 if(osbuf == NULL)
4672 return A_NO_MEMORY;
4674 A_NETBUF_PUT(osbuf, len);
4675 data = A_NETBUF_DATA(osbuf);
4676 memcpy(data, buf, len);
4678 return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
4679 NO_SYNC_WMIFLAG));
4682 #endif
4685 wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
4687 void *osbuf;
4688 WMI_SET_BT_STATUS_CMD *cmd;
4690 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status));
4692 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4693 if (osbuf == NULL) {
4694 return A_NO_MEMORY;
4697 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4699 cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4700 A_MEMZERO(cmd, sizeof(*cmd));
4701 cmd->streamType = streamType;
4702 cmd->status = status;
4704 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
4705 NO_SYNC_WMIFLAG));
4709 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
4711 void *osbuf;
4712 WMI_SET_BT_PARAMS_CMD* alloc_cmd;
4714 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType));
4716 if (cmd->paramType == BT_PARAM_SCO) {
4717 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,
4718 cmd->info.scoParams.dataResponseTimeout,
4719 cmd->info.scoParams.stompScoRules,
4720 cmd->info.scoParams.scoOptFlags,
4721 cmd->info.scoParams.stompDutyCyleVal,
4722 cmd->info.scoParams.stompDutyCyleMaxVal,
4723 cmd->info.scoParams.psPollLatencyFraction,
4724 cmd->info.scoParams.noSCOSlots,
4725 cmd->info.scoParams.noIdleSlots,
4726 cmd->info.scoParams.scoOptOffRssi,
4727 cmd->info.scoParams.scoOptOnRssi,
4728 cmd->info.scoParams.scoOptRtsCount));
4730 else if (cmd->paramType == BT_PARAM_A2DP) {
4731 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit,
4732 cmd->info.a2dpParams.a2dpBurstCntMin,
4733 cmd->info.a2dpParams.a2dpDataRespTimeout,
4734 cmd->info.a2dpParams.a2dpOptFlags,
4735 cmd->info.a2dpParams.isCoLocatedBtRoleMaster,
4736 cmd->info.a2dpParams.a2dpOptOffRssi,
4737 cmd->info.a2dpParams.a2dpOptOnRssi,
4738 cmd->info.a2dpParams.a2dpOptRtsCount));
4740 else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) {
4741 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType));
4743 else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) {
4744 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev));
4746 else if (cmd->paramType == BT_PARAM_ACLCOEX) {
4747 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime,
4748 cmd->info.aclCoexParams.aclBtMediumUsageTime,
4749 cmd->info.aclCoexParams.aclDataRespTimeout));
4751 else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) {
4752 A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG));
4755 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4756 if (osbuf == NULL) {
4757 return A_NO_MEMORY;
4760 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4762 alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
4763 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4764 memcpy(alloc_cmd, cmd, sizeof(*cmd));
4766 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
4767 NO_SYNC_WMIFLAG));
4771 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
4773 void *osbuf;
4774 WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd;
4776 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4777 if (osbuf == NULL) {
4778 return A_NO_MEMORY;
4780 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4781 alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
4782 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4783 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
4784 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
4785 NO_SYNC_WMIFLAG));
4791 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
4792 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
4794 void *osbuf;
4795 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd;
4797 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4798 if (osbuf == NULL) {
4799 return A_NO_MEMORY;
4801 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4802 alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
4803 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4804 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
4805 A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
4806 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
4807 NO_SYNC_WMIFLAG));
4812 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
4813 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
4815 void *osbuf;
4816 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd;
4818 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4819 if (osbuf == NULL) {
4820 return A_NO_MEMORY;
4822 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4823 alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4824 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4825 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
4826 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
4827 NO_SYNC_WMIFLAG));
4832 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
4833 WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
4835 void *osbuf;
4836 WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd;
4838 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4839 if (osbuf == NULL) {
4840 return A_NO_MEMORY;
4842 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4843 alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4844 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4845 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
4846 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
4847 NO_SYNC_WMIFLAG));
4852 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
4853 WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
4855 void *osbuf;
4856 WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd;
4858 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4859 if (osbuf == NULL) {
4860 return A_NO_MEMORY;
4862 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4863 alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4864 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4865 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
4866 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
4867 NO_SYNC_WMIFLAG));
4872 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
4873 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
4875 void *osbuf;
4876 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd;
4878 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4879 if (osbuf == NULL) {
4880 return A_NO_MEMORY;
4882 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4883 alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4884 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4885 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
4886 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
4887 NO_SYNC_WMIFLAG));
4892 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
4894 void *osbuf;
4895 WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd;
4897 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4898 if (osbuf == NULL) {
4899 return A_NO_MEMORY;
4901 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4902 alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
4903 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4904 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
4905 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
4906 NO_SYNC_WMIFLAG));
4911 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
4912 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
4914 void *osbuf;
4915 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd;
4917 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4918 if (osbuf == NULL) {
4919 return A_NO_MEMORY;
4921 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4922 alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
4923 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4924 memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
4925 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
4926 NO_SYNC_WMIFLAG));
4931 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
4933 void *osbuf;
4934 WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd;
4936 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4937 if (osbuf == NULL) {
4938 return A_NO_MEMORY;
4940 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4941 alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
4942 A_MEMZERO(alloc_cmd, sizeof(*cmd));
4943 memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
4944 return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
4945 NO_SYNC_WMIFLAG));
4950 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
4953 return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID);
4958 wmi_get_keepalive_configured(struct wmi_t *wmip)
4960 void *osbuf;
4961 WMI_GET_KEEPALIVE_CMD *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 cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4968 A_MEMZERO(cmd, sizeof(*cmd));
4969 return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
4970 NO_SYNC_WMIFLAG));
4973 u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
4975 return wmip->wmi_keepaliveInterval;
4979 wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
4981 void *osbuf;
4982 WMI_SET_KEEPALIVE_CMD *cmd;
4984 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
4985 if (osbuf == NULL) {
4986 return A_NO_MEMORY;
4989 A_NETBUF_PUT(osbuf, sizeof(*cmd));
4991 cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
4992 A_MEMZERO(cmd, sizeof(*cmd));
4993 cmd->keepaliveInterval = keepaliveInterval;
4994 wmip->wmi_keepaliveInterval = keepaliveInterval;
4996 return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
4997 NO_SYNC_WMIFLAG));
5001 wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
5003 void *osbuf;
5004 WMI_SET_PARAMS_CMD *cmd;
5006 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length);
5007 if (osbuf == NULL) {
5008 return A_NO_MEMORY;
5011 A_NETBUF_PUT(osbuf, sizeof(*cmd) + length);
5013 cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5014 A_MEMZERO(cmd, sizeof(*cmd));
5015 cmd->opcode = opcode;
5016 cmd->length = length;
5017 memcpy(cmd->buffer, buffer, length);
5019 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
5020 NO_SYNC_WMIFLAG));
5025 wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
5027 void *osbuf;
5028 WMI_SET_MCAST_FILTER_CMD *cmd;
5030 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5031 if (osbuf == NULL) {
5032 return A_NO_MEMORY;
5035 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5037 cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5038 cmd->multicast_mac[0] = 0x01;
5039 cmd->multicast_mac[1] = 0x00;
5040 cmd->multicast_mac[2] = 0x5e;
5041 cmd->multicast_mac[3] = dot2&0x7F;
5042 cmd->multicast_mac[4] = dot3;
5043 cmd->multicast_mac[5] = dot4;
5045 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID,
5046 NO_SYNC_WMIFLAG));
5051 wmi_del_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_DEL_MCAST_FILTER_CMDID,
5072 NO_SYNC_WMIFLAG));
5076 wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
5078 void *osbuf;
5079 WMI_MCAST_FILTER_CMD *cmd;
5081 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5082 if (osbuf == NULL) {
5083 return A_NO_MEMORY;
5086 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5088 cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
5089 cmd->enable = enable;
5091 return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID,
5092 NO_SYNC_WMIFLAG));
5096 wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
5097 u8 *ieInfo)
5099 void *osbuf;
5100 WMI_SET_APPIE_CMD *cmd;
5101 u16 cmdLen;
5103 cmdLen = sizeof(*cmd) + ieLen - 1;
5104 osbuf = A_NETBUF_ALLOC(cmdLen);
5105 if (osbuf == NULL) {
5106 return A_NO_MEMORY;
5109 A_NETBUF_PUT(osbuf, cmdLen);
5111 cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
5112 A_MEMZERO(cmd, cmdLen);
5114 cmd->mgmtFrmType = mgmtFrmType;
5115 cmd->ieLen = ieLen;
5116 memcpy(cmd->ieInfo, ieInfo, ieLen);
5118 return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
5122 wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
5124 void *osbuf;
5125 u8 *data;
5127 osbuf = A_NETBUF_ALLOC(dataLen);
5128 if (osbuf == NULL) {
5129 return A_NO_MEMORY;
5132 A_NETBUF_PUT(osbuf, dataLen);
5134 data = A_NETBUF_DATA(osbuf);
5136 memcpy(data, cmd, dataLen);
5138 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
5141 s32 wmi_get_rate(s8 rateindex)
5143 if (rateindex == RATE_AUTO) {
5144 return 0;
5145 } else {
5146 return(wmi_rateTable[(u32) rateindex][0]);
5150 void
5151 wmi_node_return (struct wmi_t *wmip, bss_t *bss)
5153 if (NULL != bss)
5155 wlan_node_return (&wmip->wmi_scan_table, bss);
5159 void
5160 wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
5162 wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
5165 bss_t *
5166 wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
5167 u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
5169 bss_t *node = NULL;
5170 node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
5171 ssidLength, bIsWPA2, bMatchSSID);
5172 return node;
5176 #ifdef THREAD_X
5177 void
5178 wmi_refresh_scan_table (struct wmi_t *wmip)
5180 wlan_refresh_inactive_nodes (&wmip->wmi_scan_table);
5182 #endif
5184 void
5185 wmi_free_allnodes(struct wmi_t *wmip)
5187 wlan_free_allnodes(&wmip->wmi_scan_table);
5190 bss_t *
5191 wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
5193 bss_t *ni=NULL;
5194 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5195 return ni;
5198 void
5199 wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
5201 bss_t *ni=NULL;
5203 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
5204 if (ni != NULL) {
5205 wlan_node_reclaim(&wmip->wmi_scan_table, ni);
5208 return;
5212 wmi_dset_open_reply(struct wmi_t *wmip,
5213 u32 status,
5214 u32 access_cookie,
5215 u32 dset_size,
5216 u32 dset_version,
5217 u32 targ_handle,
5218 u32 targ_reply_fn,
5219 u32 targ_reply_arg)
5221 void *osbuf;
5222 WMIX_DSETOPEN_REPLY_CMD *open_reply;
5224 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip));
5226 osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
5227 if (osbuf == NULL) {
5228 return A_NO_MEMORY;
5231 A_NETBUF_PUT(osbuf, sizeof(*open_reply));
5232 open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5234 open_reply->status = status;
5235 open_reply->targ_dset_handle = targ_handle;
5236 open_reply->targ_reply_fn = targ_reply_fn;
5237 open_reply->targ_reply_arg = targ_reply_arg;
5238 open_reply->access_cookie = access_cookie;
5239 open_reply->size = dset_size;
5240 open_reply->version = dset_version;
5242 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
5243 NO_SYNC_WMIFLAG));
5246 static int
5247 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5249 WMI_PMKID_LIST_REPLY *reply;
5250 u32 expected_len;
5252 if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
5253 return A_EINVAL;
5255 reply = (WMI_PMKID_LIST_REPLY *)datap;
5256 expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
5258 if (len < expected_len) {
5259 return A_EINVAL;
5262 A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
5263 reply->pmkidList, reply->bssidList[0]);
5265 return 0;
5269 static int
5270 wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5272 WMI_SET_PARAMS_REPLY *reply;
5274 if (len < sizeof(WMI_SET_PARAMS_REPLY)) {
5275 return A_EINVAL;
5277 reply = (WMI_SET_PARAMS_REPLY *)datap;
5279 if (0 == reply->status)
5283 else
5288 return 0;
5293 static int
5294 wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
5296 WMI_ACM_REJECT_EVENT *ev;
5298 ev = (WMI_ACM_REJECT_EVENT *)datap;
5299 wmip->wmi_traffic_class = ev->trafficClass;
5300 printk("ACM REJECT %d\n",wmip->wmi_traffic_class);
5301 return 0;
5305 #ifdef CONFIG_HOST_DSET_SUPPORT
5307 wmi_dset_data_reply(struct wmi_t *wmip,
5308 u32 status,
5309 u8 *user_buf,
5310 u32 length,
5311 u32 targ_buf,
5312 u32 targ_reply_fn,
5313 u32 targ_reply_arg)
5315 void *osbuf;
5316 WMIX_DSETDATA_REPLY_CMD *data_reply;
5317 u32 size;
5319 size = sizeof(*data_reply) + length;
5321 if (size <= length) {
5322 return A_ERROR;
5325 A_DPRINTF(DBG_WMI,
5326 (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
5328 osbuf = A_NETBUF_ALLOC(size);
5329 if (osbuf == NULL) {
5330 return A_NO_MEMORY;
5332 A_NETBUF_PUT(osbuf, size);
5333 data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
5335 data_reply->status = status;
5336 data_reply->targ_buf = targ_buf;
5337 data_reply->targ_reply_fn = targ_reply_fn;
5338 data_reply->targ_reply_arg = targ_reply_arg;
5339 data_reply->length = length;
5341 if (status == 0) {
5342 if (a_copy_from_user(data_reply->buf, user_buf, length)) {
5343 A_NETBUF_FREE(osbuf);
5344 return A_ERROR;
5348 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
5349 NO_SYNC_WMIFLAG));
5351 #endif /* CONFIG_HOST_DSET_SUPPORT */
5354 wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
5356 void *osbuf;
5357 char *cmd;
5359 wps_enable = status;
5361 osbuf = a_netbuf_alloc(sizeof(1));
5362 if (osbuf == NULL) {
5363 return A_NO_MEMORY;
5366 a_netbuf_put(osbuf, sizeof(1));
5368 cmd = (char *)(a_netbuf_to_data(osbuf));
5370 A_MEMZERO(cmd, sizeof(*cmd));
5371 cmd[0] = (status?1:0);
5372 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
5373 NO_SYNC_WMIFLAG));
5376 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
5378 wmi_prof_cfg_cmd(struct wmi_t *wmip,
5379 u32 period,
5380 u32 nbins)
5382 void *osbuf;
5383 WMIX_PROF_CFG_CMD *cmd;
5385 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5386 if (osbuf == NULL) {
5387 return A_NO_MEMORY;
5390 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5392 cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf));
5393 A_MEMZERO(cmd, sizeof(*cmd));
5394 cmd->period = period;
5395 cmd->nbins = nbins;
5397 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
5401 wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
5403 void *osbuf;
5404 WMIX_PROF_ADDR_SET_CMD *cmd;
5406 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5407 if (osbuf == NULL) {
5408 return A_NO_MEMORY;
5411 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5413 cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf));
5414 A_MEMZERO(cmd, sizeof(*cmd));
5415 cmd->addr = addr;
5417 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
5421 wmi_prof_start_cmd(struct wmi_t *wmip)
5423 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
5427 wmi_prof_stop_cmd(struct wmi_t *wmip)
5429 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
5433 wmi_prof_count_get_cmd(struct wmi_t *wmip)
5435 return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
5438 /* Called to handle WMIX_PROF_CONT_EVENTID */
5439 static int
5440 wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
5442 WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
5444 A_DPRINTF(DBG_WMI,
5445 (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG,
5446 prof_data->addr, prof_data->count));
5448 A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
5450 return 0;
5452 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
5454 #ifdef OS_ROAM_MANAGEMENT
5456 #define ETHERNET_MAC_ADDRESS_LENGTH 6
5458 void
5459 wmi_scan_indication (struct wmi_t *wmip)
5461 struct ieee80211_node_table *nt;
5462 u32 gen;
5463 u32 size;
5464 u32 bsssize;
5465 bss_t *bss;
5466 u32 numbss;
5467 PNDIS_802_11_BSSID_SCAN_INFO psi;
5468 PBYTE pie;
5469 NDIS_802_11_FIXED_IEs *pFixed;
5470 NDIS_802_11_VARIABLE_IEs *pVar;
5471 u32 RateSize;
5473 struct ar6kScanIndication
5475 NDIS_802_11_STATUS_INDICATION ind;
5476 NDIS_802_11_BSSID_SCAN_INFO_LIST slist;
5477 } *pAr6kScanIndEvent;
5479 nt = &wmip->wmi_scan_table;
5481 ++nt->nt_si_gen;
5484 gen = nt->nt_si_gen;
5486 size = offsetof(struct ar6kScanIndication, slist) +
5487 offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo);
5489 numbss = 0;
5491 IEEE80211_NODE_LOCK(nt);
5493 //calc size
5494 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5495 if (bss->ni_si_gen != gen) {
5496 bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs);
5497 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5499 #ifdef SUPPORT_WPA2
5500 if (bss->ni_cie.ie_rsn) {
5501 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5503 #endif
5504 if (bss->ni_cie.ie_wpa) {
5505 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5508 // bsssize must be a multiple of 4 to maintain alignment.
5509 bsssize = (bsssize + 3) & ~3;
5511 size += bsssize;
5513 numbss++;
5517 if (0 == numbss)
5519 // RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n"));
5520 ar6000_scan_indication (wmip->wmi_devt, NULL, 0);
5521 IEEE80211_NODE_UNLOCK (nt);
5522 return;
5525 pAr6kScanIndEvent = A_MALLOC(size);
5527 if (NULL == pAr6kScanIndEvent)
5529 IEEE80211_NODE_UNLOCK(nt);
5530 return;
5533 A_MEMZERO(pAr6kScanIndEvent, size);
5535 //copy data
5536 pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList;
5537 pAr6kScanIndEvent->slist.Version = 1;
5538 pAr6kScanIndEvent->slist.NumItems = numbss;
5540 psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0];
5542 for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) {
5543 if (bss->ni_si_gen != gen) {
5545 bss->ni_si_gen = gen;
5547 //Set scan time
5548 psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC;
5550 // Copy data to bssid_ex
5551 bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs);
5552 bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs);
5554 #ifdef SUPPORT_WPA2
5555 if (bss->ni_cie.ie_rsn) {
5556 bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2;
5558 #endif
5559 if (bss->ni_cie.ie_wpa) {
5560 bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2;
5563 // bsssize must be a multiple of 4 to maintain alignment.
5564 bsssize = (bsssize + 3) & ~3;
5566 psi->Bssid.Length = bsssize;
5568 memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH);
5571 //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) ||
5572 // ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70)))
5573 // RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5]));
5575 psi->Bssid.Ssid.SsidLength = 0;
5576 pie = bss->ni_cie.ie_ssid;
5578 if (pie) {
5579 // Format of SSID IE is:
5580 // Type (1 octet)
5581 // Length (1 octet)
5582 // SSID (Length octets)
5584 // Validation of the IE should have occurred within WMI.
5586 if (pie[1] <= 32) {
5587 psi->Bssid.Ssid.SsidLength = pie[1];
5588 memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength);
5591 psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0;
5593 //Post the RSSI value relative to the Standard Noise floor value.
5594 psi->Bssid.Rssi = bss->ni_rssi;
5596 if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) {
5598 if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) {
5599 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24;
5601 else {
5602 psi->Bssid.NetworkTypeInUse = Ndis802_11DS;
5605 else {
5606 psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5;
5609 psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration);
5610 psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us)
5611 psi->Bssid.Configuration.ATIMWindow = 0;
5612 psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000;
5613 psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS;
5615 RateSize = 0;
5616 pie = bss->ni_cie.ie_rates;
5617 if (pie) {
5618 RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX;
5619 memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize);
5621 pie = bss->ni_cie.ie_xrates;
5622 if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) {
5623 memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2],
5624 (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize));
5627 // Copy the fixed IEs
5628 psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs);
5630 pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs;
5631 memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp));
5632 pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt;
5633 pFixed->Capabilities = bss->ni_cie.ie_capInfo;
5635 // Copy selected variable IEs
5637 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs));
5639 #ifdef SUPPORT_WPA2
5640 // Copy the WPAv2 IE
5641 if (bss->ni_cie.ie_rsn) {
5642 pie = bss->ni_cie.ie_rsn;
5643 psi->Bssid.IELength += pie[1] + 2;
5644 memcpy(pVar, pie, pie[1] + 2);
5645 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5647 #endif
5648 // Copy the WPAv1 IE
5649 if (bss->ni_cie.ie_wpa) {
5650 pie = bss->ni_cie.ie_wpa;
5651 psi->Bssid.IELength += pie[1] + 2;
5652 memcpy(pVar, pie, pie[1] + 2);
5653 pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2);
5656 // Advance buffer pointer
5657 psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid));
5661 IEEE80211_NODE_UNLOCK(nt);
5663 // wmi_free_allnodes(wmip);
5665 // RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss));
5667 ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size);
5669 kfree(pAr6kScanIndEvent);
5671 #endif
5673 u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5674 u32 size)
5676 u32 index;
5677 u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
5679 /* The list is already in sorted order. Get the next lower value */
5680 for (index = 0; index < size; index ++) {
5681 if (rssi < sq_thresh->upper_threshold[index]) {
5682 threshold = (u8)sq_thresh->upper_threshold[index];
5683 break;
5687 return threshold;
5690 u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
5691 u32 size)
5693 u32 index;
5694 u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
5696 /* The list is already in sorted order. Get the next lower value */
5697 for (index = 0; index < size; index ++) {
5698 if (rssi > sq_thresh->lower_threshold[index]) {
5699 threshold = (u8)sq_thresh->lower_threshold[index];
5700 break;
5704 return threshold;
5706 static int
5707 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
5708 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
5710 void *osbuf;
5711 s8 size;
5712 WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
5714 size = sizeof (*cmd);
5716 osbuf = A_NETBUF_ALLOC(size);
5717 if (osbuf == NULL) {
5718 return A_NO_MEMORY;
5721 A_NETBUF_PUT(osbuf, size);
5723 cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5724 A_MEMZERO(cmd, size);
5725 memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
5727 return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
5728 NO_SYNC_WMIFLAG));
5730 static int
5731 wmi_send_snr_threshold_params(struct wmi_t *wmip,
5732 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
5734 void *osbuf;
5735 s8 size;
5736 WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
5738 size = sizeof (*cmd);
5740 osbuf = A_NETBUF_ALLOC(size);
5741 if (osbuf == NULL) {
5742 return A_NO_MEMORY;
5745 A_NETBUF_PUT(osbuf, size);
5746 cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
5747 A_MEMZERO(cmd, size);
5748 memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
5750 return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
5751 NO_SYNC_WMIFLAG));
5755 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
5757 void *osbuf;
5758 WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd;
5760 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
5761 if (osbuf == NULL) {
5762 return A_NO_MEMORY;
5765 A_NETBUF_PUT(osbuf, sizeof(*cmd));
5767 alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
5768 A_MEMZERO(alloc_cmd, sizeof(*cmd));
5769 memcpy(alloc_cmd, cmd, sizeof(*cmd));
5771 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
5772 NO_SYNC_WMIFLAG));
5775 bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
5777 wmi_get_current_bssid (wmip, id);
5778 return wlan_node_remove (&wmip->wmi_scan_table, id);
5781 int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
5783 wlan_setup_node (&wmip->wmi_scan_table, bss, id);
5784 return 0;
5787 static int
5788 wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5790 WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
5792 A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
5794 return 0;
5798 static int
5799 wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5801 WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
5803 A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
5805 return 0;
5808 static int
5809 wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5811 WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
5813 A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
5815 return 0;
5819 wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5821 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5823 A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
5825 return 0;
5830 wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
5832 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
5834 A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
5836 return 0;
5840 static int
5841 wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5843 WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
5844 A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
5846 return 0;
5849 ////////////////////////////////////////////////////////////////////////////////
5850 //// ////
5851 //// AP mode functions ////
5852 //// ////
5853 ////////////////////////////////////////////////////////////////////////////////
5855 * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG
5857 * When AR6K in AP mode, This command will be called after
5858 * changing ssid, channel etc. It will pass the profile to
5859 * target with a flag which will indicate which parameter changed,
5860 * also if this flag is 0, there was no change in parametes, so
5861 * commit cmd will not be sent to target. Without calling this IOCTL
5862 * the changes will not take effect.
5865 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
5867 void *osbuf;
5868 WMI_CONNECT_CMD *cm;
5870 osbuf = A_NETBUF_ALLOC(sizeof(*cm));
5871 if (osbuf == NULL) {
5872 return A_NO_MEMORY;
5875 A_NETBUF_PUT(osbuf, sizeof(*cm));
5876 cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
5877 A_MEMZERO(cm, sizeof(*cm));
5879 memcpy(cm,p,sizeof(*cm));
5881 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
5885 * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID
5887 * This command will be used to enable/disable hidden ssid functioanlity of
5888 * beacon. If it is enabled, ssid will be NULL in beacon.
5891 wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
5893 void *osbuf;
5894 WMI_AP_HIDDEN_SSID_CMD *hs;
5896 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD));
5897 if (osbuf == NULL) {
5898 return A_NO_MEMORY;
5901 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD));
5902 hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf));
5903 A_MEMZERO(hs, sizeof(*hs));
5905 hs->hidden_ssid = hidden_ssid;
5907 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid));
5908 return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG));
5912 * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA
5914 * This command is used to limit max num of STA that can connect
5915 * with this AP. This value should not exceed AP_MAX_NUM_STA (this
5916 * is max num of STA supported by AP). Value was already validated
5917 * in ioctl.c
5920 wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
5922 void *osbuf;
5923 WMI_AP_SET_NUM_STA_CMD *ns;
5925 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD));
5926 if (osbuf == NULL) {
5927 return A_NO_MEMORY;
5930 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD));
5931 ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf));
5932 A_MEMZERO(ns, sizeof(*ns));
5934 ns->num_sta = num_sta;
5936 A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta));
5937 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG));
5941 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC
5943 * This command is used to send list of mac of STAs which will
5944 * be allowed to connect with this AP. When this list is empty
5945 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5948 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
5950 void *osbuf;
5951 WMI_AP_ACL_MAC_CMD *a;
5953 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD));
5954 if (osbuf == NULL) {
5955 return A_NO_MEMORY;
5958 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
5959 a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
5960 A_MEMZERO(a, sizeof(*a));
5961 memcpy(a,acl,sizeof(*acl));
5963 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
5967 * IOCTL: AR6000_XIOCTL_AP_SET_MLME
5969 * This command is used to send list of mac of STAs which will
5970 * be allowed to connect with this AP. When this list is empty
5971 * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
5974 wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
5976 void *osbuf;
5977 WMI_AP_SET_MLME_CMD *mlme;
5979 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD));
5980 if (osbuf == NULL) {
5981 return A_NO_MEMORY;
5984 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD));
5985 mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf));
5986 A_MEMZERO(mlme, sizeof(*mlme));
5988 mlme->cmd = cmd;
5989 memcpy(mlme->mac, mac, ATH_MAC_LEN);
5990 mlme->reason = reason;
5992 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
5995 static int
5996 wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
5998 WMI_PSPOLL_EVENT *ev;
6000 if (len < sizeof(WMI_PSPOLL_EVENT)) {
6001 return A_EINVAL;
6003 ev = (WMI_PSPOLL_EVENT *)datap;
6005 A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
6006 return 0;
6009 static int
6010 wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6012 A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
6013 return 0;
6016 #ifdef WAPI_ENABLE
6017 static int
6018 wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
6020 u8 *ev;
6022 if (len < 7) {
6023 return A_EINVAL;
6025 ev = (u8 *)datap;
6027 A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
6028 return 0;
6030 #endif
6033 wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
6035 WMI_AP_SET_PVB_CMD *cmd;
6036 void *osbuf = NULL;
6038 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD));
6039 if (osbuf == NULL) {
6040 return A_NO_MEMORY;
6043 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD));
6044 cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf));
6045 A_MEMZERO(cmd, sizeof(*cmd));
6047 cmd->aid = aid;
6048 cmd->flag = flag;
6050 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
6054 wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
6056 WMI_AP_CONN_INACT_CMD *cmd;
6057 void *osbuf = NULL;
6059 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD));
6060 if (osbuf == NULL) {
6061 return A_NO_MEMORY;
6064 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD));
6065 cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf));
6066 A_MEMZERO(cmd, sizeof(*cmd));
6068 cmd->period = period;
6070 return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
6074 wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
6076 WMI_AP_PROT_SCAN_TIME_CMD *cmd;
6077 void *osbuf = NULL;
6079 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6080 if (osbuf == NULL) {
6081 return A_NO_MEMORY;
6084 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD));
6085 cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf));
6086 A_MEMZERO(cmd, sizeof(*cmd));
6088 cmd->period_min = period;
6089 cmd->dwell_ms = dwell;
6091 return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
6095 wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
6097 WMI_AP_SET_DTIM_CMD *cmd;
6098 void *osbuf = NULL;
6100 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD));
6101 if (osbuf == NULL) {
6102 return A_NO_MEMORY;
6105 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD));
6106 cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf));
6107 A_MEMZERO(cmd, sizeof(*cmd));
6109 cmd->dtim = dtim;
6111 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG));
6115 * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY
6117 * This command is used to set ACL policay. While changing policy, if you
6118 * want to retain the existing MAC addresses in the ACL list, policy should be
6119 * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
6120 * If there is no chage in policy, the list will be intact.
6123 wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
6125 void *osbuf;
6126 WMI_AP_ACL_POLICY_CMD *po;
6128 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD));
6129 if (osbuf == NULL) {
6130 return A_NO_MEMORY;
6133 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD));
6134 po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
6135 A_MEMZERO(po, sizeof(*po));
6137 po->policy = policy;
6139 return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
6143 wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
6145 void *osbuf;
6146 WMI_AP_SET_11BG_RATESET_CMD *rs;
6148 osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6149 if (osbuf == NULL) {
6150 return A_NO_MEMORY;
6153 A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD));
6154 rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf));
6155 A_MEMZERO(rs, sizeof(*rs));
6157 rs->rateset = rateset;
6159 return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG));
6163 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
6165 void *osbuf;
6166 WMI_SET_HT_CAP_CMD *htCap;
6167 u8 band;
6169 osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
6170 if (osbuf == NULL) {
6171 return A_NO_MEMORY;
6174 A_NETBUF_PUT(osbuf, sizeof(*htCap));
6176 band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ;
6177 wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0;
6179 htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
6180 A_MEMZERO(htCap, sizeof(*htCap));
6181 memcpy(htCap, cmd, sizeof(*htCap));
6183 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
6184 NO_SYNC_WMIFLAG));
6188 wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
6190 void *osbuf;
6191 WMI_SET_HT_OP_CMD *htInfo;
6193 osbuf = A_NETBUF_ALLOC(sizeof(*htInfo));
6194 if (osbuf == NULL) {
6195 return A_NO_MEMORY;
6198 A_NETBUF_PUT(osbuf, sizeof(*htInfo));
6200 htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf));
6201 A_MEMZERO(htInfo, sizeof(*htInfo));
6202 htInfo->sta_chan_width = sta_chan_width;
6204 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID,
6205 NO_SYNC_WMIFLAG));
6209 wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
6211 void *osbuf;
6212 WMI_SET_TX_SELECT_RATES_CMD *pData;
6214 osbuf = A_NETBUF_ALLOC(sizeof(*pData));
6215 if (osbuf == NULL) {
6216 return A_NO_MEMORY;
6219 A_NETBUF_PUT(osbuf, sizeof(*pData));
6221 pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
6222 memcpy(pData, pMaskArray, sizeof(*pData));
6224 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
6225 NO_SYNC_WMIFLAG));
6230 wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
6232 void *osbuf;
6233 WMI_HCI_CMD *cmd;
6235 osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz);
6236 if (osbuf == NULL) {
6237 return A_NO_MEMORY;
6240 A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz);
6241 cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
6243 cmd->cmd_buf_sz = sz;
6244 memcpy(cmd->buf, buf, sz);
6245 return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
6249 wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
6251 void *osbuf;
6252 WMI_ALLOW_AGGR_CMD *cmd;
6254 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6255 if (osbuf == NULL) {
6256 return A_NO_MEMORY;
6259 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6261 cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf));
6262 cmd->tx_allow_aggr = tx_tidmask;
6263 cmd->rx_allow_aggr = rx_tidmask;
6265 return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
6269 wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
6271 void *osbuf;
6272 WMI_ADDBA_REQ_CMD *cmd;
6274 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6275 if (osbuf == NULL) {
6276 return A_NO_MEMORY;
6279 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6281 cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6282 cmd->tid = tid;
6284 return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6288 wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
6290 void *osbuf;
6291 WMI_DELBA_REQ_CMD *cmd;
6293 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6294 if (osbuf == NULL) {
6295 return A_NO_MEMORY;
6298 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6300 cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf));
6301 cmd->tid = tid;
6302 cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */
6304 /* Delete the local aggr state, on host */
6305 return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG));
6309 wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
6310 bool rxDot11Hdr, bool defragOnHost)
6312 void *osbuf;
6313 WMI_RX_FRAME_FORMAT_CMD *cmd;
6315 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6316 if (osbuf == NULL) {
6317 return A_NO_MEMORY;
6320 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6322 cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
6323 cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
6324 cmd->defragOnHost = (defragOnHost==true)? 1:0;
6325 cmd->metaVersion = rxMetaVersion; /* */
6327 /* Delete the local aggr state, on host */
6328 return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG));
6333 wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
6335 void *osbuf;
6336 WMI_SET_THIN_MODE_CMD *cmd;
6338 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6339 if (osbuf == NULL) {
6340 return A_NO_MEMORY;
6343 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6345 cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
6346 cmd->enable = (bThinMode==true)? 1:0;
6348 /* Delete the local aggr state, on host */
6349 return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
6354 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
6356 void *osbuf;
6357 WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd;
6359 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6360 if (osbuf == NULL) {
6361 return A_NO_MEMORY;
6364 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6366 cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf));
6367 A_MEMZERO(cmd, sizeof(*cmd));
6368 cmd->precedence = precedence;
6370 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
6371 NO_SYNC_WMIFLAG));
6375 wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
6377 void *osbuf;
6378 WMI_SET_PMK_CMD *p;
6380 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD));
6381 if (osbuf == NULL) {
6382 return A_NO_MEMORY;
6385 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD));
6387 p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
6388 A_MEMZERO(p, sizeof(*p));
6390 memcpy(p->pmk, pmk, WMI_PMK_LEN);
6392 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
6396 wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
6398 void *osbuf;
6399 WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
6401 osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6402 if (osbuf == NULL) {
6403 return A_NO_MEMORY;
6406 A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
6408 p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
6409 memset(p, 0, sizeof(*p));
6411 p->threshold = cmd->threshold;
6413 return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
6417 wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
6419 void *osbuf;
6420 WMI_SET_TX_SGI_PARAM_CMD *cmd;
6422 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
6423 if (osbuf == NULL) {
6424 return A_NO_MEMORY ;
6427 A_NETBUF_PUT(osbuf, sizeof(*cmd));
6429 cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf));
6430 A_MEMZERO(cmd, sizeof(*cmd));
6431 cmd->sgiMask = sgiMask;
6432 cmd->sgiPERThreshold = sgiPERThreshold;
6433 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID,
6434 NO_SYNC_WMIFLAG));
6437 bss_t *
6438 wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
6439 u32 ssidLength,
6440 u32 dot11AuthMode, u32 authMode,
6441 u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
6443 bss_t *node = NULL;
6444 node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
6445 ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp);
6447 return node;
6450 u16 wmi_ieee2freq (int chan)
6452 u16 freq = 0;
6453 freq = wlan_ieee2freq (chan);
6454 return freq;
6458 u32 wmi_freq2ieee (u16 freq)
6460 u16 chan = 0;
6461 chan = wlan_freq2ieee (freq);
6462 return chan;