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