summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/include/proto/802.11.h3081
-rw-r--r--src/common/include/proto/802.1d.h40
-rw-r--r--src/common/include/proto/bcmeth.h62
-rw-r--r--src/common/include/proto/bcmevent.h343
-rw-r--r--src/common/include/proto/bcmip.h196
-rw-r--r--src/common/include/proto/ethernet.h156
-rw-r--r--src/common/include/proto/ieee80211_radiotap.h161
-rw-r--r--src/common/include/proto/wpa.h148
-rw-r--r--src/include/bcmcrypto/tkhash.h33
-rw-r--r--src/include/bcmdefs.h164
-rw-r--r--src/include/bcmendian.h280
-rw-r--r--src/include/bcmutils.h657
-rw-r--r--src/include/epivers.h41
-rw-r--r--src/include/linux_osl.h338
-rw-r--r--src/include/linuxver.h594
-rw-r--r--src/include/osl.h132
-rw-r--r--src/include/packed_section_end.h41
-rw-r--r--src/include/packed_section_start.h48
-rw-r--r--src/include/pcicfg.h83
-rw-r--r--src/include/siutils.h409
-rw-r--r--src/include/typedefs.h217
-rw-r--r--src/include/wlioctl.h1165
-rw-r--r--src/shared/bcmwifi/include/bcmwifi_channels.h353
-rw-r--r--src/shared/bcmwifi/include/bcmwifi_rates.h705
-rw-r--r--src/shared/linux_osl.c1107
-rw-r--r--src/wl/sys/wl_cfg80211_hybrid.c3022
-rw-r--r--src/wl/sys/wl_cfg80211_hybrid.h231
-rw-r--r--src/wl/sys/wl_dbg.h74
-rw-r--r--src/wl/sys/wl_export.h81
-rw-r--r--src/wl/sys/wl_iw.c2830
-rw-r--r--src/wl/sys/wl_iw.h150
-rw-r--r--src/wl/sys/wl_linux.c3371
-rw-r--r--src/wl/sys/wl_linux.h192
-rw-r--r--src/wl/sys/wlc_ethereal.h129
-rw-r--r--src/wl/sys/wlc_key.h76
-rw-r--r--src/wl/sys/wlc_pub.h927
-rw-r--r--src/wl/sys/wlc_types.h137
-rw-r--r--src/wl/sys/wlc_utils.h51
-rw-r--r--src/wl/sys/wlc_wowl.h86
39 files changed, 21911 insertions, 0 deletions
diff --git a/src/common/include/proto/802.11.h b/src/common/include/proto/802.11.h
new file mode 100644
index 0000000..5b0ccb8
--- /dev/null
+++ b/src/common/include/proto/802.11.h
@@ -0,0 +1,3081 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.11
+ *
+ * $Id: 802.11.h 394280 2013-04-01 23:04:24Z $
+ */
+
+#ifndef _802_11_H_
+#define _802_11_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#ifndef _NET_ETHERNET_H_
+#include <proto/ethernet.h>
+#endif
+
+#include <proto/wpa.h>
+
+#include <packed_section_start.h>
+
+#define DOT11_TU_TO_US 1024
+
+#define DOT11_A3_HDR_LEN 24
+#define DOT11_A4_HDR_LEN 30
+#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN
+#define DOT11_FCS_LEN 4
+#define DOT11_ICV_LEN 4
+#define DOT11_ICV_AES_LEN 8
+#define DOT11_QOS_LEN 2
+#define DOT11_HTC_LEN 4
+
+#define DOT11_KEY_INDEX_SHIFT 6
+#define DOT11_IV_LEN 4
+#define DOT11_IV_TKIP_LEN 8
+#define DOT11_IV_AES_OCB_LEN 4
+#define DOT11_IV_AES_CCM_LEN 8
+#define DOT11_IV_MAX_LEN 8
+
+#define DOT11_MAX_MPDU_BODY_LEN 2304
+
+#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \
+ DOT11_QOS_LEN + \
+ DOT11_IV_AES_CCM_LEN + \
+ DOT11_MAX_MPDU_BODY_LEN + \
+ DOT11_ICV_LEN + \
+ DOT11_FCS_LEN)
+
+#define DOT11_MAX_SSID_LEN 32
+
+#define DOT11_DEFAULT_RTS_LEN 2347
+#define DOT11_MAX_RTS_LEN 2347
+
+#define DOT11_MIN_FRAG_LEN 256
+#define DOT11_MAX_FRAG_LEN 2346
+#define DOT11_DEFAULT_FRAG_LEN 2346
+
+#define DOT11_MIN_BEACON_PERIOD 1
+#define DOT11_MAX_BEACON_PERIOD 0xFFFF
+
+#define DOT11_MIN_DTIM_PERIOD 1
+#define DOT11_MAX_DTIM_PERIOD 0xFF
+
+#define DOT11_LLC_SNAP_HDR_LEN 8
+#define DOT11_OUI_LEN 3
+BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header {
+ uint8 dsap;
+ uint8 ssap;
+ uint8 ctl;
+ uint8 oui[DOT11_OUI_LEN];
+ uint16 type;
+} BWL_POST_PACKED_STRUCT;
+
+#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)
+
+BWL_PRE_PACKED_STRUCT struct dot11_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr a1;
+ struct ether_addr a2;
+ struct ether_addr a3;
+ uint16 seq;
+ struct ether_addr a4;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_RTS_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_cts_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTS_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_ack_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACK_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr bssid;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_PS_POLL_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CS_END_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1040];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr {
+ uint8 category;
+ uint8 OUI[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t;
+#define DOT11_ACTION_VS_HDR_LEN 6
+
+#define BCM_ACTION_OUI_BYTE0 0x00
+#define BCM_ACTION_OUI_BYTE1 0x90
+#define BCM_ACTION_OUI_BYTE2 0x4c
+
+#define DOT11_BA_CTL_POLICY_NORMAL 0x0000
+#define DOT11_BA_CTL_POLICY_NOACK 0x0001
+#define DOT11_BA_CTL_POLICY_MASK 0x0001
+
+#define DOT11_BA_CTL_MTID 0x0002
+#define DOT11_BA_CTL_COMPRESSED 0x0004
+
+#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0
+#define DOT11_BA_CTL_NUMMSDU_SHIFT 6
+
+#define DOT11_BA_CTL_TID_MASK 0xF000
+#define DOT11_BA_CTL_TID_SHIFT 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_ctl_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr ra;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTL_HDR_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_bar {
+ uint16 bar_control;
+ uint16 seqnum;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BAR_LEN 4
+
+#define DOT11_BA_BITMAP_LEN 128
+#define DOT11_BA_CMP_BITMAP_LEN 8
+
+BWL_PRE_PACKED_STRUCT struct dot11_ba {
+ uint16 ba_control;
+ uint16 seqnum;
+ uint8 bitmap[DOT11_BA_BITMAP_LEN];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BA_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_management_header {
+ uint16 fc;
+ uint16 durid;
+ struct ether_addr da;
+ struct ether_addr sa;
+ struct ether_addr bssid;
+ uint16 seq;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_HDR_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb {
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 capability;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BCN_PRB_LEN 12
+#define DOT11_BCN_PRB_FIXED_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_auth {
+ uint16 alg;
+ uint16 seq;
+ uint16 status;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_AUTH_FIXED_LEN 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_req {
+ uint16 capability;
+ uint16 listen;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_REQ_FIXED_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req {
+ uint16 capability;
+ uint16 listen;
+ struct ether_addr ap;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_REASSOC_REQ_FIXED_LEN 10
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp {
+ uint16 capability;
+ uint16 status;
+ uint16 aid;
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_RESP_FIXED_LEN 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_measure {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_MEASURE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width {
+ uint8 category;
+ uint8 action;
+ uint8 ch_width;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops {
+ uint8 category;
+ uint8 action;
+ uint8 control;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query {
+ uint8 category;
+ uint8 action;
+ uint16 id;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_vht_oper_mode {
+ uint8 category;
+ uint8 action;
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+
+#define SM_PWRSAVE_ENABLE 1
+#define SM_PWRSAVE_MODE 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_power_cnst {
+ uint8 id;
+ uint8 len;
+ uint8 power;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cnst dot11_power_cnst_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_power_cap {
+ uint8 min;
+ uint8 max;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_power_cap dot11_power_cap_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep {
+ uint8 id;
+ uint8 len;
+ uint8 tx_pwr;
+ uint8 margin;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tpc_rep dot11_tpc_rep_t;
+#define DOT11_MNG_IE_TPC_REPORT_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_supp_channels {
+ uint8 id;
+ uint8 len;
+ uint8 first_channel;
+ uint8 num_channels;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_supp_channels dot11_supp_channels_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_extch {
+ uint8 id;
+ uint8 len;
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extch dot11_extch_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ uint8 extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t;
+
+#define BRCM_EXTCH_IE_LEN 5
+#define BRCM_EXTCH_IE_TYPE 53
+#define DOT11_EXTCH_IE_LEN 1
+#define DOT11_EXT_CH_MASK 0x03
+#define DOT11_EXT_CH_UPPER 0x01
+#define DOT11_EXT_CH_LOWER 0x03
+#define DOT11_EXT_CH_NONE 0x00
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr {
+ uint8 category;
+ uint8 action;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ACTION_FRMHDR_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 mode;
+ uint8 channel;
+ uint8 count;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
+
+#define DOT11_SWITCH_IE_LEN 3
+
+#define DOT11_CSA_MODE_ADVISORY 0
+#define DOT11_CSA_MODE_NO_TX 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
+ uint8 category;
+ uint8 action;
+ dot11_chan_switch_ie_t chan_switch_ie;
+ dot11_brcm_extch_ie_t extch_ie;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
+ uint8 mode;
+ uint8 reg;
+ uint8 channel;
+ uint8 count;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
+ uint8 id;
+ uint8 len;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
+#define DOT11_EXT_CSA_IE_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ dot11_ext_csa_ie_t chan_switch_ie;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch {
+ uint8 id;
+ uint8 len;
+ uint8 channel_width;
+ uint8 center_frequency_segment_0;
+ uint8 center_frequency_segment_1;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wide_bw_channel_switch dot11_wide_bw_chan_switch_ie_t;
+
+#define DOT11_WIDE_BW_SWITCH_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper {
+ uint8 id;
+ uint8 len;
+ dot11_wide_bw_chan_switch_ie_t wb_chan_switch_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch_wrapper dot11_chan_switch_wrapper_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope {
+ uint8 id;
+ uint8 len;
+ uint8 transmit_power_info;
+ uint8 local_max_transmit_power_20;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_vht_transmit_power_envelope dot11_vht_transmit_power_envelope_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_coex {
+ uint8 id;
+ uint8 len;
+ uint8 info;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_coex dot11_obss_coex_t;
+#define DOT11_OBSS_COEXINFO_LEN 1
+
+#define DOT11_OBSS_COEX_INFO_REQ 0x01
+#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02
+#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist {
+ uint8 id;
+ uint8 len;
+ uint8 regclass;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_chanlist dot11_obss_chanlist_t;
+#define DOT11_OBSS_CHANLIST_FIXED_LEN 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie {
+ uint8 id;
+ uint8 len;
+ uint8 cap[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap_ie dot11_extcap_ie_t;
+
+#define DOT11_EXTCAP_LEN_MAX 8
+#define DOT11_EXTCAP_LEN_COEX 1
+#define DOT11_EXTCAP_LEN_BT 3
+#define DOT11_EXTCAP_LEN_IW 4
+#define DOT11_EXTCAP_LEN_SI 6
+
+#define DOT11_EXTCAP_LEN_TDLS 5
+#define DOT11_11AC_EXTCAP_LEN_TDLS 8
+
+#define DOT11_EXTCAP_LEN_FMS 2
+#define DOT11_EXTCAP_LEN_PROXY_ARP 2
+#define DOT11_EXTCAP_LEN_TFS 3
+#define DOT11_EXTCAP_LEN_WNM_SLEEP 3
+#define DOT11_EXTCAP_LEN_TIMBC 3
+#define DOT11_EXTCAP_LEN_BSS_TRANSITION 3
+#define DOT11_EXTCAP_LEN_DMS 4
+#define DOT11_EXTCAP_LEN_WNM_NOTIFICATION 6
+#define DOT11_EXTCAP_LEN_TDLS_WBW 8
+#define DOT11_EXTCAP_LEN_OPMODE_NOTIFICATION 8
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap {
+ uint8 extcap[DOT11_EXTCAP_LEN_MAX];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap dot11_extcap_t;
+
+#define DOT11_TDLS_CAP_TDLS 37
+#define DOT11_TDLS_CAP_PU_BUFFER_STA 28
+#define DOT11_TDLS_CAP_PEER_PSM 20
+#define DOT11_TDLS_CAP_CH_SW 30
+#define DOT11_TDLS_CAP_PROH 38
+#define DOT11_TDLS_CAP_CH_SW_PROH 39
+#define DOT11_TDLS_CAP_TDLS_WIDER_BW 61
+
+#define DOT11_MEASURE_TYPE_BASIC 0
+#define DOT11_MEASURE_TYPE_CCA 1
+#define DOT11_MEASURE_TYPE_RPI 2
+#define DOT11_MEASURE_TYPE_CHLOAD 3
+#define DOT11_MEASURE_TYPE_NOISE 4
+#define DOT11_MEASURE_TYPE_BEACON 5
+#define DOT11_MEASURE_TYPE_FRAME 6
+#define DOT11_MEASURE_TYPE_STAT 7
+#define DOT11_MEASURE_TYPE_LCI 8
+#define DOT11_MEASURE_TYPE_TXSTREAM 9
+#define DOT11_MEASURE_TYPE_PAUSE 255
+
+#define DOT11_MEASURE_MODE_PARALLEL (1<<0)
+#define DOT11_MEASURE_MODE_ENABLE (1<<1)
+#define DOT11_MEASURE_MODE_REQUEST (1<<2)
+#define DOT11_MEASURE_MODE_REPORT (1<<3)
+#define DOT11_MEASURE_MODE_DUR (1<<4)
+
+#define DOT11_MEASURE_MODE_LATE (1<<0)
+#define DOT11_MEASURE_MODE_INCAPABLE (1<<1)
+#define DOT11_MEASURE_MODE_REFUSED (1<<2)
+
+#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0))
+#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1))
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2))
+#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3))
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4))
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_req {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_req dot11_meas_req_t;
+#define DOT11_MNG_IE_MREQ_LEN 14
+
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ BWL_PRE_PACKED_STRUCT union
+ {
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+ } BWL_POST_PACKED_STRUCT basic;
+ uint8 data[1];
+ } BWL_POST_PACKED_STRUCT rep;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep dot11_meas_rep_t;
+
+#define DOT11_MNG_IE_MREP_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic {
+ uint8 channel;
+ uint8 start_time[8];
+ uint16 duration;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t;
+#define DOT11_MEASURE_BASIC_REP_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_quiet {
+ uint8 id;
+ uint8 len;
+ uint8 count;
+ uint8 period;
+ uint16 duration;
+ uint16 offset;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_quiet dot11_quiet_t;
+
+BWL_PRE_PACKED_STRUCT struct chan_map_tuple {
+ uint8 channel;
+ uint8 map;
+} BWL_POST_PACKED_STRUCT;
+typedef struct chan_map_tuple chan_map_tuple_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs {
+ uint8 id;
+ uint8 len;
+ uint8 eaddr[ETHER_ADDR_LEN];
+ uint8 interval;
+ chan_map_tuple_t map[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ibss_dfs dot11_ibss_dfs_t;
+
+#define WME_OUI "\x00\x50\xf2"
+#define WME_OUI_LEN 3
+#define WME_OUI_TYPE 2
+#define WME_TYPE 2
+#define WME_SUBTYPE_IE 0
+#define WME_SUBTYPE_PARAM_IE 1
+#define WME_SUBTYPE_TSPEC 2
+#define WME_VER 1
+
+#define AC_BE 0
+#define AC_BK 1
+#define AC_VI 2
+#define AC_VO 3
+#define AC_COUNT 4
+
+typedef uint8 ac_bitmap_t;
+
+#define AC_BITMAP_NONE 0x0
+#define AC_BITMAP_ALL 0xf
+#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0)
+#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac))))
+#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac))))
+
+BWL_PRE_PACKED_STRUCT struct wme_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_ie wme_ie_t;
+#define WME_IE_LEN 7
+
+BWL_PRE_PACKED_STRUCT struct edcf_acparam {
+ uint8 ACI;
+ uint8 ECW;
+ uint16 TXOP;
+} BWL_POST_PACKED_STRUCT;
+typedef struct edcf_acparam edcf_acparam_t;
+
+BWL_PRE_PACKED_STRUCT struct wme_param_ie {
+ uint8 oui[3];
+ uint8 type;
+ uint8 subtype;
+ uint8 version;
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct wme_param_ie wme_param_ie_t;
+#define WME_PARAM_IE_LEN 24
+
+#define WME_QI_AP_APSD_MASK 0x80
+#define WME_QI_AP_APSD_SHIFT 7
+#define WME_QI_AP_COUNT_MASK 0x0f
+#define WME_QI_AP_COUNT_SHIFT 0
+
+#define WME_QI_STA_MAXSPLEN_MASK 0x60
+#define WME_QI_STA_MAXSPLEN_SHIFT 5
+#define WME_QI_STA_APSD_ALL_MASK 0xf
+#define WME_QI_STA_APSD_ALL_SHIFT 0
+#define WME_QI_STA_APSD_BE_MASK 0x8
+#define WME_QI_STA_APSD_BE_SHIFT 3
+#define WME_QI_STA_APSD_BK_MASK 0x4
+#define WME_QI_STA_APSD_BK_SHIFT 2
+#define WME_QI_STA_APSD_VI_MASK 0x2
+#define WME_QI_STA_APSD_VI_SHIFT 1
+#define WME_QI_STA_APSD_VO_MASK 0x1
+#define WME_QI_STA_APSD_VO_SHIFT 0
+
+#define EDCF_AIFSN_MIN 1
+#define EDCF_AIFSN_MAX 15
+#define EDCF_AIFSN_MASK 0x0f
+#define EDCF_ACM_MASK 0x10
+#define EDCF_ACI_MASK 0x60
+#define EDCF_ACI_SHIFT 5
+#define EDCF_AIFSN_SHIFT 12
+
+#define EDCF_ECW_MIN 0
+#define EDCF_ECW_MAX 15
+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK 0x0f
+#define EDCF_ECWMAX_MASK 0xf0
+#define EDCF_ECWMAX_SHIFT 4
+
+#define EDCF_TXOP_MIN 0
+#define EDCF_TXOP_MAX 65535
+#define EDCF_TXOP2USEC(txop) ((txop) << 5)
+
+#define NON_EDCF_AC_BE_ACI_STA 0x02
+
+#define EDCF_AC_BE_ACI_STA 0x03
+#define EDCF_AC_BE_ECW_STA 0xA4
+#define EDCF_AC_BE_TXOP_STA 0x0000
+#define EDCF_AC_BK_ACI_STA 0x27
+#define EDCF_AC_BK_ECW_STA 0xA4
+#define EDCF_AC_BK_TXOP_STA 0x0000
+#define EDCF_AC_VI_ACI_STA 0x42
+#define EDCF_AC_VI_ECW_STA 0x43
+#define EDCF_AC_VI_TXOP_STA 0x005e
+#define EDCF_AC_VO_ACI_STA 0x62
+#define EDCF_AC_VO_ECW_STA 0x32
+#define EDCF_AC_VO_TXOP_STA 0x002f
+
+#define EDCF_AC_BE_ACI_AP 0x03
+#define EDCF_AC_BE_ECW_AP 0x64
+#define EDCF_AC_BE_TXOP_AP 0x0000
+#define EDCF_AC_BK_ACI_AP 0x27
+#define EDCF_AC_BK_ECW_AP 0xA4
+#define EDCF_AC_BK_TXOP_AP 0x0000
+#define EDCF_AC_VI_ACI_AP 0x41
+#define EDCF_AC_VI_ECW_AP 0x43
+#define EDCF_AC_VI_TXOP_AP 0x005e
+#define EDCF_AC_VO_ACI_AP 0x61
+#define EDCF_AC_VO_ECW_AP 0x32
+#define EDCF_AC_VO_TXOP_AP 0x002f
+
+BWL_PRE_PACKED_STRUCT struct edca_param_ie {
+ uint8 qosinfo;
+ uint8 rsvd;
+ edcf_acparam_t acparam[AC_COUNT];
+} BWL_POST_PACKED_STRUCT;
+typedef struct edca_param_ie edca_param_ie_t;
+#define EDCA_PARAM_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct qos_cap_ie {
+ uint8 qosinfo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct qos_cap_ie qos_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie {
+ uint8 id;
+ uint8 length;
+ uint16 station_count;
+ uint8 channel_utilization;
+ uint16 aac;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+#define BSS_LOAD_IE_SIZE 7
+
+#define FIXED_MSDU_SIZE 0x8000
+#define MSDU_SIZE_MASK 0x7fff
+
+#define INTEGER_SHIFT 13
+#define FRACTION_MASK 0x1FFF
+
+BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_NOTIFICATION_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct ti_ie {
+ uint8 ti_type;
+ uint32 ti_val;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ti_ie ti_ie_t;
+#define TI_TYPE_REASSOC_DEADLINE 1
+#define TI_TYPE_KEY_LIFETIME 2
+
+#define WME_ADDTS_REQUEST 0
+#define WME_ADDTS_RESPONSE 1
+#define WME_DELTS_REQUEST 2
+
+#define WME_ADMISSION_ACCEPTED 0
+#define WME_INVALID_PARAMETERS 1
+#define WME_ADMISSION_REFUSED 3
+
+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
+
+#define DOT11_OPEN_SYSTEM 0
+#define DOT11_SHARED_KEY 1
+#define DOT11_FAST_BSS 2
+#define DOT11_CHALLENGE_LEN 128
+
+#define FC_PVER_MASK 0x3
+#define FC_PVER_SHIFT 0
+#define FC_TYPE_MASK 0xC
+#define FC_TYPE_SHIFT 2
+#define FC_SUBTYPE_MASK 0xF0
+#define FC_SUBTYPE_SHIFT 4
+#define FC_TODS 0x100
+#define FC_TODS_SHIFT 8
+#define FC_FROMDS 0x200
+#define FC_FROMDS_SHIFT 9
+#define FC_MOREFRAG 0x400
+#define FC_MOREFRAG_SHIFT 10
+#define FC_RETRY 0x800
+#define FC_RETRY_SHIFT 11
+#define FC_PM 0x1000
+#define FC_PM_SHIFT 12
+#define FC_MOREDATA 0x2000
+#define FC_MOREDATA_SHIFT 13
+#define FC_WEP 0x4000
+#define FC_WEP_SHIFT 14
+#define FC_ORDER 0x8000
+#define FC_ORDER_SHIFT 15
+
+#define SEQNUM_SHIFT 4
+#define SEQNUM_MAX 0x1000
+#define FRAGNUM_MASK 0xF
+
+#define FC_TYPE_MNG 0
+#define FC_TYPE_CTL 1
+#define FC_TYPE_DATA 2
+
+#define FC_SUBTYPE_ASSOC_REQ 0
+#define FC_SUBTYPE_ASSOC_RESP 1
+#define FC_SUBTYPE_REASSOC_REQ 2
+#define FC_SUBTYPE_REASSOC_RESP 3
+#define FC_SUBTYPE_PROBE_REQ 4
+#define FC_SUBTYPE_PROBE_RESP 5
+#define FC_SUBTYPE_BEACON 8
+#define FC_SUBTYPE_ATIM 9
+#define FC_SUBTYPE_DISASSOC 10
+#define FC_SUBTYPE_AUTH 11
+#define FC_SUBTYPE_DEAUTH 12
+#define FC_SUBTYPE_ACTION 13
+#define FC_SUBTYPE_ACTION_NOACK 14
+
+#define FC_SUBTYPE_CTL_WRAPPER 7
+#define FC_SUBTYPE_BLOCKACK_REQ 8
+#define FC_SUBTYPE_BLOCKACK 9
+#define FC_SUBTYPE_PS_POLL 10
+#define FC_SUBTYPE_RTS 11
+#define FC_SUBTYPE_CTS 12
+#define FC_SUBTYPE_ACK 13
+#define FC_SUBTYPE_CF_END 14
+#define FC_SUBTYPE_CF_END_ACK 15
+
+#define FC_SUBTYPE_DATA 0
+#define FC_SUBTYPE_DATA_CF_ACK 1
+#define FC_SUBTYPE_DATA_CF_POLL 2
+#define FC_SUBTYPE_DATA_CF_ACK_POLL 3
+#define FC_SUBTYPE_NULL 4
+#define FC_SUBTYPE_CF_ACK 5
+#define FC_SUBTYPE_CF_POLL 6
+#define FC_SUBTYPE_CF_ACK_POLL 7
+#define FC_SUBTYPE_QOS_DATA 8
+#define FC_SUBTYPE_QOS_DATA_CF_ACK 9
+#define FC_SUBTYPE_QOS_DATA_CF_POLL 10
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11
+#define FC_SUBTYPE_QOS_NULL 12
+#define FC_SUBTYPE_QOS_CF_POLL 14
+#define FC_SUBTYPE_QOS_CF_ACK_POLL 15
+
+#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0)
+#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0)
+#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0)
+#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0)
+
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK)
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
+
+#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT)
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)
+
+#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)
+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK)
+
+#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER)
+#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ)
+#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK)
+#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)
+#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)
+#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)
+#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)
+#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)
+#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)
+
+#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)
+#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)
+#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)
+#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)
+#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)
+
+#define QOS_PRIO_SHIFT 0
+#define QOS_PRIO_MASK 0x0007
+#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)
+
+#define QOS_TID_SHIFT 0
+#define QOS_TID_MASK 0x000f
+#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT)
+
+#define QOS_EOSP_SHIFT 4
+#define QOS_EOSP_MASK 0x0010
+#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT)
+
+#define QOS_ACK_NORMAL_ACK 0
+#define QOS_ACK_NO_ACK 1
+#define QOS_ACK_NO_EXP_ACK 2
+#define QOS_ACK_BLOCK_ACK 3
+#define QOS_ACK_SHIFT 5
+#define QOS_ACK_MASK 0x0060
+#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)
+
+#define QOS_AMSDU_SHIFT 7
+#define QOS_AMSDU_MASK 0x0080
+
+#define DOT11_MNG_AUTH_ALGO_LEN 2
+#define DOT11_MNG_AUTH_SEQ_LEN 2
+#define DOT11_MNG_BEACON_INT_LEN 2
+#define DOT11_MNG_CAP_LEN 2
+#define DOT11_MNG_AP_ADDR_LEN 6
+#define DOT11_MNG_LISTEN_INT_LEN 2
+#define DOT11_MNG_REASON_LEN 2
+#define DOT11_MNG_AID_LEN 2
+#define DOT11_MNG_STATUS_LEN 2
+#define DOT11_MNG_TIMESTAMP_LEN 8
+
+#define DOT11_AID_MASK 0x3fff
+
+#define DOT11_RC_RESERVED 0
+#define DOT11_RC_UNSPECIFIED 1
+#define DOT11_RC_AUTH_INVAL 2
+#define DOT11_RC_DEAUTH_LEAVING 3
+#define DOT11_RC_INACTIVITY 4
+#define DOT11_RC_BUSY 5
+#define DOT11_RC_INVAL_CLASS_2 6
+#define DOT11_RC_INVAL_CLASS_3 7
+#define DOT11_RC_DISASSOC_LEAVING 8
+#define DOT11_RC_NOT_AUTH 9
+#define DOT11_RC_BAD_PC 10
+#define DOT11_RC_BAD_CHANNELS 11
+
+#define DOT11_RC_UNSPECIFIED_QOS 32
+#define DOT11_RC_INSUFFCIENT_BW 33
+#define DOT11_RC_EXCESSIVE_FRAMES 34
+#define DOT11_RC_TX_OUTSIDE_TXOP 35
+#define DOT11_RC_LEAVING_QBSS 36
+#define DOT11_RC_BAD_MECHANISM 37
+#define DOT11_RC_SETUP_NEEDED 38
+#define DOT11_RC_TIMEOUT 39
+
+#define DOT11_RC_MAX 23
+
+#define DOT11_RC_TDLS_PEER_UNREACH 25
+#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26
+
+#define DOT11_SC_SUCCESS 0
+#define DOT11_SC_FAILURE 1
+#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2
+
+#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3
+#define DOT11_SC_TDLS_SEC_DISABLED 5
+#define DOT11_SC_LIFETIME_REJ 6
+#define DOT11_SC_NOT_SAME_BSS 7
+#define DOT11_SC_CAP_MISMATCH 10
+#define DOT11_SC_REASSOC_FAIL 11
+#define DOT11_SC_ASSOC_FAIL 12
+#define DOT11_SC_AUTH_MISMATCH 13
+#define DOT11_SC_AUTH_SEQ 14
+#define DOT11_SC_AUTH_CHALLENGE_FAIL 15
+#define DOT11_SC_AUTH_TIMEOUT 16
+#define DOT11_SC_ASSOC_BUSY_FAIL 17
+#define DOT11_SC_ASSOC_RATE_MISMATCH 18
+#define DOT11_SC_ASSOC_SHORT_REQUIRED 19
+#define DOT11_SC_ASSOC_PBCC_REQUIRED 20
+#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21
+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22
+#define DOT11_SC_ASSOC_BAD_POWER_CAP 23
+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24
+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25
+#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26
+#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27
+#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28
+#define DOT11_SC_ASSOC_TRY_LATER 30
+#define DOT11_SC_ASSOC_MFP_VIOLATION 31
+
+#define DOT11_SC_DECLINED 37
+#define DOT11_SC_INVALID_PARAMS 38
+#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42
+#define DOT11_SC_INVALID_AKMP 43
+#define DOT11_SC_INVALID_RSNIE_CAP 45
+#define DOT11_SC_DLS_NOT_ALLOWED 48
+#define DOT11_SC_INVALID_PMKID 53
+#define DOT11_SC_INVALID_MDID 54
+#define DOT11_SC_INVALID_FTIE 55
+
+#define DOT11_SC_ADV_PROTO_NOT_SUPPORTED 59
+#define DOT11_SC_NO_OUTSTAND_REQ 60
+#define DOT11_SC_RSP_NOT_RX_FROM_SERVER 61
+#define DOT11_SC_TIMEOUT 62
+#define DOT11_SC_QUERY_RSP_TOO_LARGE 63
+#define DOT11_SC_SERVER_UNREACHABLE 65
+
+#define DOT11_SC_UNEXP_MSG 70
+#define DOT11_SC_INVALID_SNONCE 71
+#define DOT11_SC_INVALID_RSNIE 72
+
+#define DOT11_SC_TRANSMIT_FAILURE 79
+
+#define DOT11_MNG_DS_PARAM_LEN 1
+#define DOT11_MNG_IBSS_PARAM_LEN 2
+
+#define DOT11_MNG_TIM_FIXED_LEN 3
+#define DOT11_MNG_TIM_DTIM_COUNT 0
+#define DOT11_MNG_TIM_DTIM_PERIOD 1
+#define DOT11_MNG_TIM_BITMAP_CTL 2
+#define DOT11_MNG_TIM_PVB 3
+
+#define TLV_TAG_OFF 0
+#define TLV_LEN_OFF 1
+#define TLV_HDR_LEN 2
+#define TLV_BODY_OFF 2
+
+#define DOT11_MNG_SSID_ID 0
+#define DOT11_MNG_RATES_ID 1
+#define DOT11_MNG_FH_PARMS_ID 2
+#define DOT11_MNG_DS_PARMS_ID 3
+#define DOT11_MNG_CF_PARMS_ID 4
+#define DOT11_MNG_TIM_ID 5
+#define DOT11_MNG_IBSS_PARMS_ID 6
+#define DOT11_MNG_COUNTRY_ID 7
+#define DOT11_MNG_HOPPING_PARMS_ID 8
+#define DOT11_MNG_HOPPING_TABLE_ID 9
+#define DOT11_MNG_REQUEST_ID 10
+#define DOT11_MNG_QBSS_LOAD_ID 11
+#define DOT11_MNG_EDCA_PARAM_ID 12
+#define DOT11_MNG_TSPEC_ID 13
+#define DOT11_MNG_TCLAS_ID 14
+#define DOT11_MNG_CHALLENGE_ID 16
+#define DOT11_MNG_PWR_CONSTRAINT_ID 32
+#define DOT11_MNG_PWR_CAP_ID 33
+#define DOT11_MNG_TPC_REQUEST_ID 34
+#define DOT11_MNG_TPC_REPORT_ID 35
+#define DOT11_MNG_SUPP_CHANNELS_ID 36
+#define DOT11_MNG_CHANNEL_SWITCH_ID 37
+#define DOT11_MNG_MEASURE_REQUEST_ID 38
+#define DOT11_MNG_MEASURE_REPORT_ID 39
+#define DOT11_MNG_QUIET_ID 40
+#define DOT11_MNG_IBSS_DFS_ID 41
+#define DOT11_MNG_ERP_ID 42
+#define DOT11_MNG_TS_DELAY_ID 43
+#define DOT11_MNG_TCLAS_PROC_ID 44
+#define DOT11_MNG_HT_CAP 45
+#define DOT11_MNG_QOS_CAP_ID 46
+#define DOT11_MNG_NONERP_ID 47
+#define DOT11_MNG_RSN_ID 48
+#define DOT11_MNG_EXT_RATES_ID 50
+#define DOT11_MNG_AP_CHREP_ID 51
+#define DOT11_MNG_NBR_REP_ID 52
+#define DOT11_MNG_RCPI_ID 53
+#define DOT11_MNG_MDIE_ID 54
+#define DOT11_MNG_FTIE_ID 55
+#define DOT11_MNG_FT_TI_ID 56
+#define DOT11_MNG_RDE_ID 57
+#define DOT11_MNG_REGCLASS_ID 59
+#define DOT11_MNG_EXT_CSA_ID 60
+#define DOT11_MNG_HT_ADD 61
+#define DOT11_MNG_EXT_CHANNEL_OFFSET 62
+#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID 63
+#define DOT11_MNG_ANTENNA_ID 64
+#define DOT11_MNG_RSNI_ID 65
+#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID 66
+#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID 67
+#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID 68
+#define DOT11_MNG_WAPI_ID 68
+#define DOT11_MNG_TIME_ADVERTISE_ID 69
+#define DOT11_MNG_RRM_CAP_ID 70
+#define DOT11_MNG_MULTIPLE_BSSID_ID 71
+#define DOT11_MNG_HT_BSS_COEXINFO_ID 72
+#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73
+#define DOT11_MNG_HT_OBSS_ID 74
+#define DOT11_MNG_MMIE_ID 76
+#define DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID 90
+#define DOT11_MNG_TFS_REQUEST_ID 91
+#define DOT11_MNG_TFS_RESPONSE_ID 92
+#define DOT11_MNG_WNM_SLEEP_MODE_ID 93
+#define DOT11_MNG_TIMBC_REQ_ID 94
+#define DOT11_MNG_TIMBC_RESP_ID 95
+#define DOT11_MNG_CHANNEL_USAGE 97
+#define DOT11_MNG_TIME_ZONE_ID 98
+#define DOT11_MNG_DMS_REQUEST_ID 99
+#define DOT11_MNG_DMS_RESPONSE_ID 100
+#define DOT11_MNG_LINK_IDENTIFIER_ID 101
+#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102
+#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104
+#define DOT11_MNG_PTI_CONTROL_ID 105
+#define DOT11_MNG_PU_BUFFER_STATUS_ID 106
+#define DOT11_MNG_INTERWORKING_ID 107
+#define DOT11_MNG_ADVERTISEMENT_ID 108
+#define DOT11_MNG_EXP_BW_REQ_ID 109
+#define DOT11_MNG_QOS_MAP_ID 110
+#define DOT11_MNG_ROAM_CONSORT_ID 111
+#define DOT11_MNG_EMERGCY_ALERT_ID 112
+#define DOT11_MNG_EXT_CAP_ID 127
+#define DOT11_MNG_VHT_CAP_ID 191
+#define DOT11_MNG_VHT_OPERATION_ID 192
+#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID 194
+#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID 195
+#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID 196
+#define DOT11_MNG_AID_ID 197
+#define DOT11_MNG_OPER_MODE_NOTIF_ID 199
+
+#define DOT11_MNG_WPA_ID 221
+#define DOT11_MNG_PROPR_ID 221
+
+#define DOT11_MNG_VS_ID 221
+
+#define DOT11_RATE_1M 2
+#define DOT11_RATE_2M 4
+#define DOT11_RATE_5M5 11
+#define DOT11_RATE_11M 22
+#define DOT11_RATE_6M 12
+#define DOT11_RATE_9M 18
+#define DOT11_RATE_12M 24
+#define DOT11_RATE_18M 36
+#define DOT11_RATE_24M 48
+#define DOT11_RATE_36M 72
+#define DOT11_RATE_48M 96
+#define DOT11_RATE_54M 108
+#define DOT11_RATE_MAX 108
+
+#define DOT11_RATE_BASIC 0x80
+#define DOT11_RATE_MASK 0x7F
+
+#define DOT11_MNG_ERP_LEN 1
+#define DOT11_MNG_NONERP_PRESENT 0x01
+#define DOT11_MNG_USE_PROTECTION 0x02
+#define DOT11_MNG_BARKER_PREAMBLE 0x04
+
+#define DOT11_MGN_TS_DELAY_LEN 4
+#define TS_DELAY_FIELD_SIZE 4
+
+#define DOT11_CAP_ESS 0x0001
+#define DOT11_CAP_IBSS 0x0002
+#define DOT11_CAP_POLLABLE 0x0004
+#define DOT11_CAP_POLL_RQ 0x0008
+#define DOT11_CAP_PRIVACY 0x0010
+#define DOT11_CAP_SHORT 0x0020
+#define DOT11_CAP_PBCC 0x0040
+#define DOT11_CAP_AGILITY 0x0080
+#define DOT11_CAP_SPECTRUM 0x0100
+#define DOT11_CAP_QOS 0x0200
+#define DOT11_CAP_SHORTSLOT 0x0400
+#define DOT11_CAP_APSD 0x0800
+#define DOT11_CAP_RRM 0x1000
+#define DOT11_CAP_CCK_OFDM 0x2000
+#define DOT11_CAP_DELAY_BA 0x4000
+#define DOT11_CAP_IMMEDIATE_BA 0x8000
+
+#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0
+
+#define DOT11_EXT_CAP_SPSMP 6
+
+#define DOT11_EXT_CAP_FMS 11
+
+#define DOT11_EXT_CAP_PROXY_ARP 12
+
+#define DOT11_EXT_CAP_TFS 16
+
+#define DOT11_EXT_CAP_WNM_SLEEP 17
+
+#define DOT11_EXT_CAP_TIMBC 18
+
+#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19
+
+#define DOT11_EXT_CAP_DMS 26
+
+#define DOT11_EXT_CAP_IW 31
+
+#define DOT11_EXT_CAP_SI 41
+#define DOT11_EXT_CAP_SI_MASK 0x0E
+
+#define DOT11_EXT_CAP_WNM_NOTIF 46
+
+#define DOT11_EXT_CAP_OPER_MODE_NOTIF 62
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT 0
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_MASK 0x3
+#define DOT11_OPER_MODE_RXNSS_SHIFT 4
+#define DOT11_OPER_MODE_RXNSS_MASK 0x70
+#define DOT11_OPER_MODE_RXNSS_TYPE_SHIFT 7
+#define DOT11_OPER_MODE_RXNSS_TYPE_MASK 0x80
+
+#define DOT11_OPER_MODE(type, nss, chanw) (\
+ ((type) << DOT11_OPER_MODE_RXNSS_TYPE_SHIFT &\
+ DOT11_OPER_MODE_RXNSS_TYPE_MASK) |\
+ (((nss) - 1) << DOT11_OPER_MODE_RXNSS_SHIFT & DOT11_OPER_MODE_RXNSS_MASK) |\
+ ((chanw) << DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT &\
+ DOT11_OPER_MODE_CHANNEL_WIDTH_MASK))
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH(mode) \
+ (((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK)\
+ >> DOT11_OPER_MODE_CHANNEL_WIDTH_SHIFT)
+#define DOT11_OPER_MODE_RXNSS(mode) \
+ ((((mode) & DOT11_OPER_MODE_RXNSS_MASK) \
+ >> DOT11_OPER_MODE_RXNSS_SHIFT) + 1)
+#define DOT11_OPER_MODE_RXNSS_TYPE(mode) \
+ (((mode) & DOT11_OPER_MODE_RXNSS_TYPE_MASK)\
+ >> DOT11_OPER_MODE_RXNSS_TYPE_SHIFT)
+
+#define DOT11_OPER_MODE_20MHZ 0
+#define DOT11_OPER_MODE_40MHZ 1
+#define DOT11_OPER_MODE_80MHZ 2
+#define DOT11_OPER_MODE_160MHZ 3
+#define DOT11_OPER_MODE_8080MHZ 3
+
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_20MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_20MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_40MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_40MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_80MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_80MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_160MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_160MHZ)
+#define DOT11_OPER_MODE_CHANNEL_WIDTH_8080MHZ(mode) (\
+ ((mode) & DOT11_OPER_MODE_CHANNEL_WIDTH_MASK) == DOT11_OPER_MODE_8080MHZ)
+
+BWL_PRE_PACKED_STRUCT struct dot11_oper_mode_notif_ie {
+ uint8 mode;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_oper_mode_notif_ie dot11_oper_mode_notif_ie_t;
+
+#define DOT11_OPER_MODE_NOTIF_IE_LEN 1
+
+#define DOT11_ACTION_HDR_LEN 2
+#define DOT11_ACTION_CAT_OFF 0
+#define DOT11_ACTION_ACT_OFF 1
+
+#define DOT11_ACTION_CAT_ERR_MASK 0x80
+#define DOT11_ACTION_CAT_MASK 0x7F
+#define DOT11_ACTION_CAT_SPECT_MNG 0
+#define DOT11_ACTION_CAT_QOS 1
+#define DOT11_ACTION_CAT_DLS 2
+#define DOT11_ACTION_CAT_BLOCKACK 3
+#define DOT11_ACTION_CAT_PUBLIC 4
+#define DOT11_ACTION_CAT_RRM 5
+#define DOT11_ACTION_CAT_FBT 6
+#define DOT11_ACTION_CAT_HT 7
+#define DOT11_ACTION_CAT_SA_QUERY 8
+#define DOT11_ACTION_CAT_PDPA 9
+#define DOT11_ACTION_CAT_WNM 10
+#define DOT11_ACTION_CAT_UWNM 11
+#define DOT11_ACTION_NOTIFICATION 17
+#define DOT11_ACTION_CAT_VHT 21
+#define DOT11_ACTION_CAT_VSP 126
+#define DOT11_ACTION_CAT_VS 127
+
+#define DOT11_SM_ACTION_M_REQ 0
+#define DOT11_SM_ACTION_M_REP 1
+#define DOT11_SM_ACTION_TPC_REQ 2
+#define DOT11_SM_ACTION_TPC_REP 3
+#define DOT11_SM_ACTION_CHANNEL_SWITCH 4
+#define DOT11_SM_ACTION_EXT_CSA 5
+
+#define DOT11_ACTION_ID_HT_CH_WIDTH 0
+#define DOT11_ACTION_ID_HT_MIMO_PS 1
+
+#define DOT11_PUB_ACTION_BSS_COEX_MNG 0
+#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4
+#define DOT11_PUB_ACTION_GAS_CB_REQ 12
+
+#define DOT11_BA_ACTION_ADDBA_REQ 0
+#define DOT11_BA_ACTION_ADDBA_RESP 1
+#define DOT11_BA_ACTION_DELBA 2
+
+#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001
+#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1
+#define DOT11_ADDBA_PARAM_TID_MASK 0x003c
+#define DOT11_ADDBA_PARAM_TID_SHIFT 2
+#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6
+
+#define DOT11_ADDBA_POLICY_DELAYED 0
+#define DOT11_ADDBA_POLICY_IMMEDIATE 1
+
+#define DOT11_FT_ACTION_FT_RESERVED 0
+#define DOT11_FT_ACTION_FT_REQ 1
+#define DOT11_FT_ACTION_FT_RES 2
+#define DOT11_FT_ACTION_FT_CON 3
+#define DOT11_FT_ACTION_FT_ACK 4
+
+#define DOT11_DLS_ACTION_REQ 0
+#define DOT11_DLS_ACTION_RESP 1
+#define DOT11_DLS_ACTION_TD 2
+
+#define DOT11_WNM_ACTION_EVENT_REQ 0
+#define DOT11_WNM_ACTION_EVENT_REP 1
+#define DOT11_WNM_ACTION_DIAG_REQ 2
+#define DOT11_WNM_ACTION_DIAG_REP 3
+#define DOT11_WNM_ACTION_LOC_CFG_REQ 4
+#define DOT11_WNM_ACTION_LOC_RFG_RESP 5
+#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6
+#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7
+#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8
+#define DOT11_WNM_ACTION_FMS_REQ 9
+#define DOT11_WNM_ACTION_FMS_RESP 10
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11
+#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12
+#define DOT11_WNM_ACTION_TFS_REQ 13
+#define DOT11_WNM_ACTION_TFS_RESP 14
+#define DOT11_WNM_ACTION_TFS_NOTIFY 15
+#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16
+#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17
+#define DOT11_WNM_ACTION_TIMBC_REQ 18
+#define DOT11_WNM_ACTION_TIMBC_RESP 19
+#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20
+#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21
+#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22
+#define DOT11_WNM_ACTION_DMS_REQ 23
+#define DOT11_WNM_ACTION_DMS_RESP 24
+#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25
+#define DOT11_WNM_ACTION_NOTFCTN_REQ 26
+#define DOT11_WNM_ACTION_NOTFCTN_RES 27
+
+#define DOT11_UWNM_ACTION_TIM 0
+#define DOT11_UWNM_ACTION_TIMING_MEASUREMENT 1
+
+#define DOT11_MNG_COUNTRY_ID_LEN 3
+
+#define DOT11_VHT_ACTION_CBF 0
+#define DOT11_VHT_ACTION_GID_MGMT 1
+#define DOT11_VHT_ACTION_OPER_MODE_NOTIF 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dls_req {
+ uint8 category;
+ uint8 action;
+ struct ether_addr da;
+ struct ether_addr sa;
+ uint16 cap;
+ uint16 timeout;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_req dot11_dls_req_t;
+#define DOT11_DLS_REQ_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_dls_resp {
+ uint8 category;
+ uint8 action;
+ uint16 status;
+ struct ether_addr da;
+ struct ether_addr sa;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_resp dot11_dls_resp_t;
+#define DOT11_DLS_RESP_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 reason;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_query dot11_bss_trans_query_t;
+#define DOT11_BSS_TRANS_QUERY_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 reqmode;
+ uint16 disassoc_tmr;
+ uint8 validity_intrvl;
+ uint8 data[1];
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_req dot11_bss_trans_req_t;
+#define DOT11_BSS_TRANS_REQ_LEN 7
+
+#define DOT11_BSS_TERM_DUR_LEN 12
+
+#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01
+#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02
+#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04
+#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08
+#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 status;
+ uint8 term_delay;
+ uint8 data[1];
+
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_trans_res dot11_bss_trans_res_t;
+#define DOT11_BSS_TRANS_RES_LEN 5
+
+#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0
+#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7
+#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8
+
+#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY_UNKNOWN 0x0002
+#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003
+#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004
+#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0
+
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100
+#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200
+
+#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3
+#define DOT11_NBR_RPRT_SUBELEM_BSS_TERM_DUR_ID 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_term_dur_subelem {
+ uint8 id;
+ uint8 len;
+ uint8 bss_term_tsf[8];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_term_dur_subelem dot11_bss_term_dur_subelem_t;
+#define DOT11_BSS_TERM_DUR_SUBELEM_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
+ uint8 id;
+ uint8 length;
+ uint16 max_idle_period;
+ uint8 idle_opt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bss_max_idle_period_ie dot11_bss_max_idle_period_ie_t;
+#define DOT11_BSS_MAX_IDLE_PERIOD_IE_LEN 3
+#define DOT11_BSS_MAX_IDLE_PERIOD_OPT_PROTECTED 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 interval;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req_ie dot11_timbc_req_ie_t;
+#define DOT11_TIMBC_REQ_IE_LEN 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req dot11_timbc_req_t;
+#define DOT11_TIMBC_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 status;
+ uint8 interval;
+ int32 offset;
+ uint16 high_rate;
+ uint16 low_rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp_ie dot11_timbc_resp_ie_t;
+#define DOT11_TIMBC_DENY_RESP_IE_LEN 1
+#define DOT11_TIMBC_ACCEPT_RESP_IE_LEN 10
+
+#define DOT11_TIMBC_STATUS_ACCEPT 0
+#define DOT11_TIMBC_STATUS_ACCEPT_TSTAMP 1
+#define DOT11_TIMBC_STATUS_DENY 2
+#define DOT11_TIMBC_STATUS_OVERRIDDEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp dot11_timbc_resp_t;
+#define DOT11_TIMBC_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tim_ie {
+ uint8 id;
+ uint8 len;
+ uint8 dtim_count;
+ uint8 dtim_period;
+ uint8 bitmap_control;
+ uint8 pvb[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tim_ie dot11_tim_ie_t;
+#define DOT11_TIM_IE_FIXED_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_timbc {
+ uint8 category;
+ uint8 action;
+ uint8 check_beacon;
+ uint8 tsf[8];
+ dot11_tim_ie_t tim_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc dot11_timbc_t;
+#define DOT11_TIMBC_HDR_LEN (sizeof(dot11_timbc_t) - sizeof(dot11_tim_ie_t))
+#define DOT11_TIMBC_FIXED_LEN (sizeof(dot11_timbc_t) - 1)
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_hdr {
+ uint8 type;
+ uint8 mask;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_hdr dot11_tclas_fc_hdr_t;
+#define DOT11_TCLAS_FC_HDR_LEN 2
+
+#define DOT11_TCLAS_MASK_0 0x1
+#define DOT11_TCLAS_MASK_1 0x2
+#define DOT11_TCLAS_MASK_2 0x4
+#define DOT11_TCLAS_MASK_3 0x8
+#define DOT11_TCLAS_MASK_4 0x10
+#define DOT11_TCLAS_MASK_5 0x20
+#define DOT11_TCLAS_MASK_6 0x40
+#define DOT11_TCLAS_MASK_7 0x80
+
+#define DOT11_TCLAS_FC_0_ETH 0
+#define DOT11_TCLAS_FC_1_IP 1
+#define DOT11_TCLAS_FC_2_8021Q 2
+#define DOT11_TCLAS_FC_3_OFFSET 3
+#define DOT11_TCLAS_FC_4_IP_HIGHER 4
+#define DOT11_TCLAS_FC_5_8021D 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_0_eth {
+ uint8 type;
+ uint8 mask;
+ uint8 sa[ETHER_ADDR_LEN];
+ uint8 da[ETHER_ADDR_LEN];
+ uint16 eth_type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_0_eth dot11_tclas_fc_0_eth_t;
+#define DOT11_TCLAS_FC_0_ETH_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_1_ipv4 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint32 src_ip;
+ uint32 dst_ip;
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 protocol;
+ uint8 reserved;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_1_ipv4_t;
+#define DOT11_TCLAS_FC_1_IPV4_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_2_8021q {
+ uint8 type;
+ uint8 mask;
+ uint16 tci;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_2_8021q dot11_tclas_fc_2_8021q_t;
+#define DOT11_TCLAS_FC_2_8021Q_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_3_filter {
+ uint8 type;
+ uint8 mask;
+ uint16 offset;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_3_filter dot11_tclas_fc_3_filter_t;
+#define DOT11_TCLAS_FC_3_FILTER_LEN 4
+
+typedef struct dot11_tclas_fc_1_ipv4 dot11_tclas_fc_4_ipv4_t;
+#define DOT11_TCLAS_FC_4_IPV4_LEN DOT11_TCLAS_FC_1_IPV4_LEN
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_4_ipv6 {
+ uint8 type;
+ uint8 mask;
+ uint8 version;
+ uint8 saddr[16];
+ uint8 daddr[16];
+ uint16 src_port;
+ uint16 dst_port;
+ uint8 dscp;
+ uint8 nexthdr;
+ uint8 flow_lbl[3];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_4_ipv6 dot11_tclas_fc_4_ipv6_t;
+#define DOT11_TCLAS_FC_4_IPV6_LEN 44
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_fc_5_8021d {
+ uint8 type;
+ uint8 mask;
+ uint8 pcp;
+ uint8 cfi;
+ uint16 vid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_fc_5_8021d dot11_tclas_fc_5_8021d_t;
+#define DOT11_TCLAS_FC_5_8021D_LEN 6
+
+BWL_PRE_PACKED_STRUCT union dot11_tclas_fc {
+ uint8 data[1];
+ dot11_tclas_fc_hdr_t hdr;
+ dot11_tclas_fc_0_eth_t t0_eth;
+ dot11_tclas_fc_1_ipv4_t t1_ipv4;
+ dot11_tclas_fc_2_8021q_t t2_8021q;
+ dot11_tclas_fc_3_filter_t t3_filter;
+ dot11_tclas_fc_4_ipv4_t t4_ipv4;
+ dot11_tclas_fc_4_ipv6_t t4_ipv6;
+ dot11_tclas_fc_5_8021d_t t5_8021d;
+} BWL_POST_PACKED_STRUCT;
+typedef union dot11_tclas_fc dot11_tclas_fc_t;
+#define DOT11_TCLAS_FC_MIN_LEN 4
+#define DOT11_TCLAS_FC_MAX_LEN 254
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_ie {
+ uint8 id;
+ uint8 length;
+ uint8 user_priority;
+ dot11_tclas_fc_t fc;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_ie dot11_tclas_ie_t;
+#define DOT11_TCLAS_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie {
+ uint8 id;
+ uint8 length;
+ uint8 process;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t;
+#define DOT11_TCLAS_PROC_IE_LEN 3
+
+#define DOT11_TCLAS_PROC_MATCHALL 0
+#define DOT11_TCLAS_PROC_MATCHONE 1
+#define DOT11_TCLAS_PROC_NONMATCH 2
+
+#define DOT11_TSPEC_IE_LEN 57
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 tfs_id;
+ uint8 tfs_actcode;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req_ie dot11_tfs_req_ie_t;
+#define DOT11_TFS_REQ_IE_LEN 4
+
+#define DOT11_TFS_ACTCODE_DELETE 1
+#define DOT11_TFS_ACTCODE_MODIFY 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
+ uint8 sub_id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_se dot11_tfs_se_t;
+
+#define DOT11_TFS_REQ_SUBELEM_LEN 2
+
+#define DOT11_TFS_SUBELEM_ID_TFS 1
+#define DOT11_TFS_SUBELEM_ID_VENDOR 221
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
+#define DOT11_TFS_RESP_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
+ uint8 id;
+ uint8 length;
+ uint8 resp_st;
+ uint8 tfs_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
+
+#define DOT11_TFS_STATUS_SE_LEN 4
+#define DOT11_TFS_STATUS_SE_DATA_LEN 2
+
+#define DOT11_TFS_STATUS_SE_ID_TFS_ST 1
+#define DOT11_TFS_STATUS_SE_ID_TFS 2
+#define DOT11_TFS_STATUS_SE_ID_VENDOR 221
+
+#define DOT11_TFS_RESP_ST_ACCEPT 0
+#define DOT11_TFS_RESP_ST_DENY_FORMAT 1
+#define DOT11_TFS_RESP_ST_DENY_RESOURCE 2
+#define DOT11_TFS_RESP_ST_DENY_POLICY 4
+#define DOT11_TFS_RESP_ST_PREFERRED_AP_INCAP 14
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req dot11_tfs_req_t;
+#define DOT11_TFS_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp dot11_tfs_resp_t;
+#define DOT11_TFS_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify {
+ uint8 category;
+ uint8 action;
+ uint8 num_tfs_id;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify dot11_tfs_notify_t;
+#define DOT11_TFS_NOTIFY_LEN 3
+
+#define DOT11_TFS_NOTIFY_ACT_DEL 1
+#define DOT11_TFS_NOTIFY_ACT_NOTIFY 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_req dot11_wnm_sleep_req_t;
+#define DOT11_WNM_SLEEP_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 key_len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_resp dot11_wnm_sleep_resp_t;
+#define DOT11_WNM_SLEEP_RESP_LEN 5
+
+#define DOT11_WNM_SLEEP_SUBELEM_ID_GTK 0
+#define DOT11_WNM_SLEEP_SUBELEM_ID_IGTK 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_gtk {
+ uint8 sub_id;
+ uint8 length;
+ uint16 key_info;
+ uint8 key_length;
+ uint8 rsc[8];
+ uint8 key[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_gtk dot11_wnm_sleep_subelem_gtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_FIXED_LEN 11
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_MAX_LEN 43
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_igtk {
+ uint8 sub_id;
+ uint8 length;
+ uint16 key_id;
+ uint8 pn[6];
+ uint8 key[16];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_subelem_igtk dot11_wnm_sleep_subelem_igtk_t;
+#define DOT11_WNM_SLEEP_SUBELEM_IGTK_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_ie {
+ uint8 id;
+ uint8 length;
+ uint8 act_type;
+ uint8 resp_status;
+ uint16 interval;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_ie dot11_wnm_sleep_ie_t;
+#define DOT11_WNM_SLEEP_IE_LEN 4
+
+#define DOT11_WNM_SLEEP_ACT_TYPE_ENTER 0
+#define DOT11_WNM_SLEEP_ACT_TYPE_EXIT 1
+
+#define DOT11_WNM_SLEEP_RESP_ACCEPT 0
+#define DOT11_WNM_SLEEP_RESP_UPDATE 1
+#define DOT11_WNM_SLEEP_RESP_DENY 2
+#define DOT11_WNM_SLEEP_RESP_DENY_TEMP 3
+#define DOT11_WNM_SLEEP_RESP_DENY_KEY 4
+#define DOT11_WNM_SLEEP_RESP_DENY_INUSE 5
+#define DOT11_WNM_SLEEP_RESP_LAST 6
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req dot11_dms_req_t;
+#define DOT11_DMS_REQ_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp dot11_dms_resp_t;
+#define DOT11_DMS_RESP_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_ie dot11_dms_req_ie_t;
+#define DOT11_DMS_REQ_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_ie {
+ uint8 id;
+ uint8 length;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_ie dot11_dms_resp_ie_t;
+#define DOT11_DMS_RESP_IE_LEN 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_desc {
+ uint8 dms_id;
+ uint8 length;
+ uint8 type;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req_desc dot11_dms_req_desc_t;
+#define DOT11_DMS_REQ_DESC_LEN 3
+
+#define DOT11_DMS_REQ_TYPE_ADD 0
+#define DOT11_DMS_REQ_TYPE_REMOVE 1
+#define DOT11_DMS_REQ_TYPE_CHANGE 2
+
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_st {
+ uint8 dms_id;
+ uint8 length;
+ uint8 type;
+ uint16 lsc;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp_st dot11_dms_resp_st_t;
+#define DOT11_DMS_RESP_STATUS_LEN 5
+
+#define DOT11_DMS_RESP_TYPE_ACCEPT 0
+#define DOT11_DMS_RESP_TYPE_DENY 1
+#define DOT11_DMS_RESP_TYPE_TERM 2
+
+#define DOT11_DMS_RESP_LSC_UNSUPPORTED 0xFFFF
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_req {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 addba_param_set;
+ uint16 timeout;
+ uint16 start_seqnum;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN 9
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_resp {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 status;
+ uint16 addba_param_set;
+ uint16 timeout;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN 9
+
+#define DOT11_DELBA_PARAM_INIT_MASK 0x0800
+#define DOT11_DELBA_PARAM_INIT_SHIFT 11
+#define DOT11_DELBA_PARAM_TID_MASK 0xf000
+#define DOT11_DELBA_PARAM_TID_SHIFT 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_delba {
+ uint8 category;
+ uint8 action;
+ uint16 delba_param_set;
+ uint16 reason;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN 6
+
+#define SA_QUERY_REQUEST 0
+#define SA_QUERY_RESPONSE 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_req {
+ uint8 category;
+ uint8 action;
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_req dot11_ft_req_t;
+#define DOT11_FT_REQ_FIXED_LEN 14
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_res {
+ uint8 category;
+ uint8 action;
+ uint8 sta_addr[ETHER_ADDR_LEN];
+ uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+ uint16 status;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_res dot11_ft_res_t;
+#define DOT11_FT_RES_FIXED_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_rde_ie {
+ uint8 id;
+ uint8 length;
+ uint8 rde_id;
+ uint8 rd_count;
+ uint16 status;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rde_ie dot11_rde_ie_t;
+
+#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t)
+
+#define DOT11_RRM_CAP_LEN 5
+#define RCPI_IE_LEN 1
+#define RSNI_IE_LEN 1
+BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie {
+ uint8 cap[DOT11_RRM_CAP_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t;
+
+#define DOT11_RRM_CAP_LINK 0
+#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1
+#define DOT11_RRM_CAP_PARALLEL 2
+#define DOT11_RRM_CAP_REPEATED 3
+#define DOT11_RRM_CAP_BCN_PASSIVE 4
+#define DOT11_RRM_CAP_BCN_ACTIVE 5
+#define DOT11_RRM_CAP_BCN_TABLE 6
+#define DOT11_RRM_CAP_BCN_REP_COND 7
+#define DOT11_RRM_CAP_AP_CHANREP 16
+
+#define DOT11_OP_CLASS_NONE 255
+
+BWL_PRE_PACKED_STRUCT struct do11_ap_chrep {
+ uint8 id;
+ uint8 len;
+ uint8 reg;
+ uint8 chanlist[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct do11_ap_chrep dot11_ap_chrep_t;
+
+#define DOT11_RM_ACTION_RM_REQ 0
+#define DOT11_RM_ACTION_RM_REP 1
+#define DOT11_RM_ACTION_LM_REQ 2
+#define DOT11_RM_ACTION_LM_REP 3
+#define DOT11_RM_ACTION_NR_REQ 4
+#define DOT11_RM_ACTION_NR_REP 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_rm_action {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_action dot11_rm_action_t;
+#define DOT11_RM_ACTION_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint16 reps;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq dot11_rmreq_t;
+#define DOT11_RMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_rm_ie {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rm_ie dot11_rm_ie_t;
+#define DOT11_RM_IE_LEN 5
+
+#define DOT11_RMREQ_MODE_PARALLEL 1
+#define DOT11_RMREQ_MODE_ENABLE 2
+#define DOT11_RMREQ_MODE_REQUEST 4
+#define DOT11_RMREQ_MODE_REPORT 8
+#define DOT11_RMREQ_MODE_DURMAND 0x10
+
+#define DOT11_RMREP_MODE_LATE 1
+#define DOT11_RMREP_MODE_INCAPABLE 2
+#define DOT11_RMREP_MODE_REFUSED 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 bcn_mode;
+ struct ether_addr bssid;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t;
+#define DOT11_RMREQ_BCN_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 frame_info;
+ uint8 rcpi;
+ uint8 rsni;
+ struct ether_addr bssid;
+ uint8 antenna_id;
+ uint32 parent_tsf;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t;
+#define DOT11_RMREP_BCN_LEN 26
+
+#define DOT11_RMREQ_BCN_PASSIVE 0
+#define DOT11_RMREQ_BCN_ACTIVE 1
+#define DOT11_RMREQ_BCN_TABLE 2
+
+#define DOT11_RMREQ_BCN_SSID_ID 0
+#define DOT11_RMREQ_BCN_REPINFO_ID 1
+#define DOT11_RMREQ_BCN_REPDET_ID 2
+#define DOT11_RMREQ_BCN_REQUEST_ID 10
+#define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID
+
+#define DOT11_RMREQ_BCN_REPDET_FIXED 0
+#define DOT11_RMREQ_BCN_REPDET_REQUEST 1
+#define DOT11_RMREQ_BCN_REPDET_ALL 2
+
+#define DOT11_RMREP_BCN_FRM_BODY 1
+
+#define DOT11_RMREP_FRAME_COUNT_REPORT 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_chanload {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_chanload dot11_rmreq_chanload_t;
+#define DOT11_RMREQ_CHANLOAD_LEN 11
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_chanload {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 channel_load;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_chanload dot11_rmrep_chanload_t;
+#define DOT11_RMREP_CHANLOAD_LEN 13
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_noise {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_noise dot11_rmreq_noise_t;
+#define DOT11_RMREQ_NOISE_LEN 11
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_noise {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+ uint8 antid;
+ uint8 anpi;
+ uint8 ipi0_dens;
+ uint8 ipi1_dens;
+ uint8 ipi2_dens;
+ uint8 ipi3_dens;
+ uint8 ipi4_dens;
+ uint8 ipi5_dens;
+ uint8 ipi6_dens;
+ uint8 ipi7_dens;
+ uint8 ipi8_dens;
+ uint8 ipi9_dens;
+ uint8 ipi10_dens;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_noise dot11_rmrep_noise_t;
+#define DOT11_RMREP_NOISE_LEN 25
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_frame {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint8 reg;
+ uint8 channel;
+ uint16 interval;
+ uint16 duration;
+ uint8 req_type;
+ struct ether_addr ta;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_frame dot11_rmreq_frame_t;
+#define DOT11_RMREQ_FRAME_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frame {
+ uint8 reg;
+ uint8 channel;
+ uint32 starttime[2];
+ uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frame dot11_rmrep_frame_t;
+#define DOT11_RMREP_FRAME_LEN 12
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frmentry {
+ struct ether_addr ta;
+ struct ether_addr bssid;
+ uint8 phy_type;
+ uint8 avg_rcpi;
+ uint8 last_rsni;
+ uint8 last_rcpi;
+ uint8 ant_id;
+ uint16 frame_cnt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_frmentry dot11_rmrep_frmentry_t;
+#define DOT11_RMREP_FRMENTRY_LEN 19
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_stat {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ struct ether_addr peer;
+ uint16 interval;
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_stat dot11_rmreq_stat_t;
+#define DOT11_RMREQ_STAT_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_stat {
+ uint16 duration;
+ uint8 group_id;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_stat dot11_rmrep_stat_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_tx_stream {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 interval;
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 bin0_range;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_tx_stream dot11_rmreq_tx_stream_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_tx_stream {
+ uint32 starttime[2];
+ uint16 duration;
+ struct ether_addr peer;
+ uint8 traffic_id;
+ uint8 reason;
+ uint32 txmsdu_cnt;
+ uint32 msdu_discarded_cnt;
+ uint32 msdufailed_cnt;
+ uint32 msduretry_cnt;
+ uint32 cfpolls_lost_cnt;
+ uint32 avrqueue_delay;
+ uint32 avrtx_delay;
+ uint8 bin0_range;
+ uint32 bin0;
+ uint32 bin1;
+ uint32 bin2;
+ uint32 bin3;
+ uint32 bin4;
+ uint32 bin5;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_tx_stream dot11_rmrep_tx_stream_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time {
+ uint8 id;
+ uint8 len;
+ uint8 token;
+ uint8 mode;
+ uint8 type;
+ uint16 pause_time;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr {
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg;
+ uint8 channel;
+ uint8 phytype;
+ uchar sub_elements[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t;
+#define DOT11_RMREP_NBR_LEN 13
+
+BWL_PRE_PACKED_STRUCT struct dot11_rrmrep_nbr {
+ uint8 id;
+ uint8 len;
+ dot11_rmrep_nbr_t nbr_rrmrep;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rrmrep_nbr dot11_rrmrep_nbr_t;
+#define DOT11_RRMREP_NBR_LEN 15
+
+#define DOT11_BSSTYPE_INFRASTRUCTURE 0
+#define DOT11_BSSTYPE_INDEPENDENT 1
+#define DOT11_BSSTYPE_ANY 2
+#define DOT11_SCANTYPE_ACTIVE 0
+#define DOT11_SCANTYPE_PASSIVE 1
+
+BWL_PRE_PACKED_STRUCT struct dot11_lmreq {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ uint8 txpwr;
+ uint8 maxtxpwr;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmreq dot11_lmreq_t;
+#define DOT11_LMREQ_LEN 5
+
+BWL_PRE_PACKED_STRUCT struct dot11_lmrep {
+ uint8 category;
+ uint8 action;
+ uint8 token;
+ dot11_tpc_rep_t tpc;
+ uint8 rxant;
+ uint8 txant;
+ uint8 rcpi;
+ uint8 rsni;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmrep dot11_lmrep_t;
+#define DOT11_LMREP_LEN 11
+
+#define PREN_PREAMBLE 24
+#define PREN_MM_EXT 12
+#define PREN_PREAMBLE_EXT 4
+
+#define RIFS_11N_TIME 2
+
+#define HT_SIG1_MCS_MASK 0x00007F
+#define HT_SIG1_CBW 0x000080
+#define HT_SIG1_HT_LENGTH 0xFFFF00
+
+#define HT_SIG2_SMOOTHING 0x000001
+#define HT_SIG2_NOT_SOUNDING 0x000002
+#define HT_SIG2_RESERVED 0x000004
+#define HT_SIG2_AGGREGATION 0x000008
+#define HT_SIG2_STBC_MASK 0x000030
+#define HT_SIG2_STBC_SHIFT 4
+#define HT_SIG2_FEC_CODING 0x000040
+#define HT_SIG2_SHORT_GI 0x000080
+#define HT_SIG2_ESS_MASK 0x000300
+#define HT_SIG2_ESS_SHIFT 8
+#define HT_SIG2_CRC 0x03FC00
+#define HT_SIG2_TAIL 0x1C0000
+
+#define HT_T_LEG_PREAMBLE 16
+#define HT_T_L_SIG 4
+#define HT_T_SIG 8
+#define HT_T_LTF1 4
+#define HT_T_GF_LTF1 8
+#define HT_T_LTFs 4
+#define HT_T_STF 4
+#define HT_T_GF_STF 8
+#define HT_T_SYML 4
+
+#define HT_N_SERVICE 16
+#define HT_N_TAIL 6
+
+#define APHY_SLOT_TIME 9
+#define APHY_SIFS_TIME 16
+#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))
+#define APHY_PREAMBLE_TIME 16
+#define APHY_SIGNAL_TIME 4
+#define APHY_SYMBOL_TIME 4
+#define APHY_SERVICE_NBITS 16
+#define APHY_TAIL_NBITS 6
+#define APHY_CWMIN 15
+
+#define BPHY_SLOT_TIME 20
+#define BPHY_SIFS_TIME 10
+#define BPHY_DIFS_TIME 50
+#define BPHY_PLCP_TIME 192
+#define BPHY_PLCP_SHORT_TIME 96
+#define BPHY_CWMIN 31
+
+#define DOT11_OFDM_SIGNAL_EXTENSION 6
+
+#define PHY_CWMAX 1023
+
+#define DOT11_MAXNUMFRAGS 16
+
+typedef int vht_group_id_t;
+
+#define VHT_SIGA1_CONST_MASK 0x800004
+
+#define VHT_SIGA1_BW_MASK 0x000003
+#define VHT_SIGA1_20MHZ_VAL 0x000000
+#define VHT_SIGA1_40MHZ_VAL 0x000001
+#define VHT_SIGA1_80MHZ_VAL 0x000002
+#define VHT_SIGA1_160MHZ_VAL 0x000003
+
+#define VHT_SIGA1_STBC 0x000008
+
+#define VHT_SIGA1_GID_MASK 0x0003f0
+#define VHT_SIGA1_GID_SHIFT 4
+#define VHT_SIGA1_GID_TO_AP 0x00
+#define VHT_SIGA1_GID_NOT_TO_AP 0x3f
+#define VHT_SIGA1_GID_MAX_GID 0x3f
+
+#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00
+#define VHT_SIGA1_NSTS_SHIFT 10
+
+#define VHT_SIGA1_PARTIAL_AID_MASK 0x3fe000
+#define VHT_SIGA1_PARTIAL_AID_SHIFT 13
+
+#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED 0x400000
+
+#define VHT_SIGA2_GI_NONE 0x000000
+#define VHT_SIGA2_GI_SHORT 0x000001
+#define VHT_SIGA2_GI_W_MOD10 0x000002
+#define VHT_SIGA2_CODING_LDPC 0x000004
+#define VHT_SIGA2_LDPC_EXTRA_OFDM_SYM 0x000008
+#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100
+#define VHT_SIGA2_MCS_SHIFT 4
+
+#define VHT_SIGA2_B9_RESERVED 0x000200
+#define VHT_SIGA2_TAIL_MASK 0xfc0000
+#define VHT_SIGA2_TAIL_VALUE 0x000000
+
+#define VHT_T_LEG_PREAMBLE 16
+#define VHT_T_L_SIG 4
+#define VHT_T_SIG_A 8
+#define VHT_T_LTF 4
+#define VHT_T_STF 4
+#define VHT_T_SIG_B 4
+#define VHT_T_SYML 4
+
+#define VHT_N_SERVICE 16
+#define VHT_N_TAIL 6
+
+typedef struct d11cnt {
+ uint32 txfrag;
+ uint32 txmulti;
+ uint32 txfail;
+ uint32 txretry;
+ uint32 txretrie;
+ uint32 rxdup;
+ uint32 txrts;
+ uint32 txnocts;
+ uint32 txnoack;
+ uint32 rxfrag;
+ uint32 rxmulti;
+ uint32 rxcrc;
+ uint32 txfrmsnt;
+ uint32 rxundec;
+} d11cnt_t;
+
+#define BRCM_PROP_OUI "\x00\x90\x4C"
+
+#define BRCM_SYSCAP_WET_TUNNEL 0x0100
+
+#define BRCM_OUI "\x00\x10\x18"
+
+BWL_PRE_PACKED_STRUCT struct brcm_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 ver;
+ uint8 assoc;
+ uint8 flags;
+ uint8 flags1;
+ uint16 amsdu_mtu_pref;
+} BWL_POST_PACKED_STRUCT;
+typedef struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN 11
+#define BRCM_IE_VER 2
+#define BRCM_IE_LEGACY_AES_VER 1
+
+#define BRF_LZWDS 0x4
+#define BRF_BLOCKACK 0x8
+
+#define BRF1_AMSDU 0x1
+#define BRF1_WMEPS 0x4
+#define BRF1_PSOFIX 0x8
+#define BRF1_RX_LARGE_AGG 0x10
+#define BRF1_RFAWARE_DCS 0x20
+#define BRF1_SOFTAP 0x40
+#define BRF1_DWDS 0x80
+
+BWL_PRE_PACKED_STRUCT struct vndr_ie {
+ uchar id;
+ uchar len;
+ uchar oui [3];
+ uchar data [1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN 2
+#define VNDR_IE_MIN_LEN 3
+#define VNDR_IE_MAX_LEN 255
+
+BWL_PRE_PACKED_STRUCT struct member_of_brcm_prop_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uint8 type;
+ struct ether_addr ea;
+} BWL_POST_PACKED_STRUCT;
+typedef struct member_of_brcm_prop_ie member_of_brcm_prop_ie_t;
+
+#define MEMBER_OF_BRCM_PROP_IE_LEN 10
+#define MEMBER_OF_BRCM_PROP_IE_TYPE 54
+
+BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
+ uchar id;
+ uchar len;
+ uchar oui[3];
+ uint8 type;
+ struct ether_addr ea;
+ struct ether_addr mcast_ea;
+ uint8 updtmo;
+} BWL_POST_PACKED_STRUCT;
+typedef struct relmcast_brcm_prop_ie relmcast_brcm_prop_ie_t;
+
+#define RELMCAST_BRCM_PROP_IE_LEN (sizeof(relmcast_brcm_prop_ie_t)-2)
+#define RELMCAST_BRCM_PROP_IE_TYPE 55
+
+#define MCSSET_LEN 16
+#define MAX_MCS_NUM (128)
+
+BWL_PRE_PACKED_STRUCT struct ht_cap_ie {
+ uint16 cap;
+ uint8 params;
+ uint8 supp_mcs[MCSSET_LEN];
+ uint16 ext_htcap;
+ uint32 txbf_cap;
+ uint8 as_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_cap_ie ht_cap_ie_t;
+BWL_PRE_PACKED_STRUCT struct dot11_ht_cap_ie {
+ uint8 id;
+ uint8 len;
+ ht_cap_ie_t ht_cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ht_cap_ie dot11_ht_cap_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ ht_cap_ie_t cap_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_cap_ie ht_prop_cap_ie_t;
+
+#define HT_PROP_IE_OVERHEAD 4
+#define HT_CAP_IE_LEN 26
+#define HT_CAP_IE_TYPE 51
+
+#define HT_CAP_LDPC_CODING 0x0001
+#define HT_CAP_40MHZ 0x0002
+#define HT_CAP_MIMO_PS_MASK 0x000C
+#define HT_CAP_MIMO_PS_SHIFT 0x0002
+#define HT_CAP_MIMO_PS_OFF 0x0003
+#define HT_CAP_MIMO_PS_RTS 0x0001
+#define HT_CAP_MIMO_PS_ON 0x0000
+#define HT_CAP_GF 0x0010
+#define HT_CAP_SHORT_GI_20 0x0020
+#define HT_CAP_SHORT_GI_40 0x0040
+#define HT_CAP_TX_STBC 0x0080
+#define HT_CAP_RX_STBC_MASK 0x0300
+#define HT_CAP_RX_STBC_SHIFT 8
+#define HT_CAP_DELAYED_BA 0x0400
+#define HT_CAP_MAX_AMSDU 0x0800
+
+#define HT_CAP_DSSS_CCK 0x1000
+#define HT_CAP_PSMP 0x2000
+#define HT_CAP_40MHZ_INTOLERANT 0x4000
+#define HT_CAP_LSIG_TXOP 0x8000
+
+#define HT_CAP_RX_STBC_NO 0x0
+#define HT_CAP_RX_STBC_ONE_STREAM 0x1
+#define HT_CAP_RX_STBC_TWO_STREAM 0x2
+#define HT_CAP_RX_STBC_THREE_STREAM 0x3
+
+#define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX 0x1
+#define HT_CAP_TXBF_CAP_NDP_TX 0x8
+#define HT_CAP_TXBF_CAP_NDP_RX 0x10
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI 0x100
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_STEERING 0x200
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_STEERING 0x400
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_MASK 0x1800
+#define HT_CAP_TXBF_CAP_EXPLICIT_CSI_FB_SHIFT 11
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_MASK 0x6000
+#define HT_CAP_TXBF_CAP_EXPLICIT_NC_FB_SHIFT 13
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_MASK 0x18000
+#define HT_CAP_TXBF_CAP_EXPLICIT_C_FB_SHIFT 15
+#define HT_CAP_TXBF_CAP_CSI_BFR_ANT_SHIFT 19
+#define HT_CAP_TXBF_CAP_NC_BFR_ANT_SHIFT 21
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_SHIFT 23
+#define HT_CAP_TXBF_CAP_C_BFR_ANT_MASK 0x1800000
+
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_SHIFT 27
+#define HT_CAP_TXBF_CAP_CHAN_ESTIM_MASK 0x18000000
+
+#define HT_CAP_TXBF_FB_TYPE_NONE 0
+#define HT_CAP_TXBF_FB_TYPE_DELAYED 1
+#define HT_CAP_TXBF_FB_TYPE_IMMEDIATE 2
+#define HT_CAP_TXBF_FB_TYPE_BOTH 3
+
+#define VHT_MAX_MPDU 11454
+#define VHT_MPDU_MSDU_DELTA 56
+
+#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA)
+
+#define HT_MAX_AMSDU 7935
+#define HT_MIN_AMSDU 3835
+
+#define HT_PARAMS_RX_FACTOR_MASK 0x03
+#define HT_PARAMS_DENSITY_MASK 0x1C
+#define HT_PARAMS_DENSITY_SHIFT 2
+
+#define AMPDU_MAX_MPDU_DENSITY 7
+#define AMPDU_DENSITY_NONE 0
+#define AMPDU_DENSITY_1over4_US 1
+#define AMPDU_DENSITY_1over2_US 2
+#define AMPDU_DENSITY_1_US 3
+#define AMPDU_DENSITY_2_US 4
+#define AMPDU_DENSITY_4_US 5
+#define AMPDU_DENSITY_8_US 6
+#define AMPDU_DENSITY_16_US 7
+#define AMPDU_RX_FACTOR_8K 0
+#define AMPDU_RX_FACTOR_16K 1
+#define AMPDU_RX_FACTOR_32K 2
+#define AMPDU_RX_FACTOR_64K 3
+#define AMPDU_RX_FACTOR_BASE 8*1024
+
+#define AMPDU_DELIMITER_LEN 4
+#define AMPDU_DELIMITER_LEN_MAX 63
+
+#define HT_CAP_EXT_PCO 0x0001
+#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006
+#define HT_CAP_EXT_PCO_TTIME_SHIFT 1
+#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300
+#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8
+#define HT_CAP_EXT_HTC 0x0400
+#define HT_CAP_EXT_RD_RESP 0x0800
+
+BWL_PRE_PACKED_STRUCT struct ht_add_ie {
+ uint8 ctl_ch;
+ uint8 byte1;
+ uint16 opmode;
+ uint16 misc_bits;
+ uint8 basic_mcs[MCSSET_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_add_ie ht_add_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie {
+ uint8 id;
+ uint8 len;
+ uint8 oui[3];
+ uint8 type;
+ ht_add_ie_t add_ie;
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_prop_add_ie ht_prop_add_ie_t;
+
+#define HT_ADD_IE_LEN 22
+#define HT_ADD_IE_TYPE 52
+
+#define HT_BW_ANY 0x04
+#define HT_RIFS_PERMITTED 0x08
+
+#define HT_OPMODE_MASK 0x0003
+#define HT_OPMODE_SHIFT 0
+#define HT_OPMODE_PURE 0x0000
+#define HT_OPMODE_OPTIONAL 0x0001
+#define HT_OPMODE_HT20IN40 0x0002
+#define HT_OPMODE_MIXED 0x0003
+#define HT_OPMODE_NONGF 0x0004
+#define DOT11N_TXBURST 0x0008
+#define DOT11N_OBSS_NONHT 0x0010
+
+#define HT_BASIC_STBC_MCS 0x007f
+#define HT_DUAL_STBC_PROT 0x0080
+#define HT_SECOND_BCN 0x0100
+#define HT_LSIG_TXOP 0x0200
+#define HT_PCO_ACTIVE 0x0400
+#define HT_PCO_PHASE 0x0800
+#define HT_DUALCTS_PROTECTION 0x0080
+
+#define DOT11N_2G_TXBURST_LIMIT 6160
+#define DOT11N_5G_TXBURST_LIMIT 3080
+
+#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ >> HT_OPMODE_SHIFT)
+#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_MIXED)
+#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_HT20IN40)
+#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+ == HT_OPMODE_OPTIONAL)
+#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \
+ HT_MIXEDMODE_PRESENT((add_ie)))
+#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \
+ == HT_OPMODE_NONGF)
+#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
+ == DOT11N_TXBURST)
+#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
+ == DOT11N_OBSS_NONHT)
+
+BWL_PRE_PACKED_STRUCT struct obss_params {
+ uint16 passive_dwell;
+ uint16 active_dwell;
+ uint16 bss_widthscan_interval;
+ uint16 passive_total;
+ uint16 active_total;
+ uint16 chanwidth_transition_dly;
+ uint16 activity_threshold;
+} BWL_POST_PACKED_STRUCT;
+typedef struct obss_params obss_params_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_obss_ie {
+ uint8 id;
+ uint8 len;
+ obss_params_t obss_params;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_obss_ie dot11_obss_ie_t;
+#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t)
+
+#define HT_CTRL_LA_TRQ 0x00000002
+#define HT_CTRL_LA_MAI 0x0000003C
+#define HT_CTRL_LA_MAI_SHIFT 2
+#define HT_CTRL_LA_MAI_MRQ 0x00000004
+#define HT_CTRL_LA_MAI_MSI 0x00000038
+#define HT_CTRL_LA_MFSI 0x000001C0
+#define HT_CTRL_LA_MFSI_SHIFT 6
+#define HT_CTRL_LA_MFB_ASELC 0x0000FE00
+#define HT_CTRL_LA_MFB_ASELC_SH 9
+#define HT_CTRL_LA_ASELC_CMD 0x00000C00
+#define HT_CTRL_LA_ASELC_DATA 0x0000F000
+#define HT_CTRL_CAL_POS 0x00030000
+#define HT_CTRL_CAL_SEQ 0x000C0000
+#define HT_CTRL_CSI_STEERING 0x00C00000
+#define HT_CTRL_CSI_STEER_SHIFT 22
+#define HT_CTRL_CSI_STEER_NFB 0
+#define HT_CTRL_CSI_STEER_CSI 1
+#define HT_CTRL_CSI_STEER_NCOM 2
+#define HT_CTRL_CSI_STEER_COM 3
+#define HT_CTRL_NDP_ANNOUNCE 0x01000000
+#define HT_CTRL_AC_CONSTRAINT 0x40000000
+#define HT_CTRL_RDG_MOREPPDU 0x80000000
+
+#define HT_OPMODE_OPTIONAL 0x0001
+#define HT_OPMODE_HT20IN40 0x0002
+#define HT_OPMODE_MIXED 0x0003
+#define HT_OPMODE_NONGF 0x0004
+#define DOT11N_TXBURST 0x0008
+#define DOT11N_OBSS_NONHT 0x0010
+
+BWL_PRE_PACKED_STRUCT struct vht_cap_ie {
+ uint32 vht_cap_info;
+
+ uint16 rx_mcs_map;
+ uint16 rx_max_rate;
+ uint16 tx_mcs_map;
+ uint16 tx_max_rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_cap_ie vht_cap_ie_t;
+
+#define VHT_CAP_IE_LEN 12
+
+#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003
+#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c
+#define VHT_CAP_INFO_LDPC 0x00000010
+#define VHT_CAP_INFO_SGI_80MHZ 0x00000020
+#define VHT_CAP_INFO_SGI_160MHZ 0x00000040
+#define VHT_CAP_INFO_TX_STBC 0x00000080
+#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700
+#define VHT_CAP_INFO_RX_STBC_SHIFT 8
+#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800
+#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000
+#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000
+#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16
+#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000
+#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000
+#define VHT_CAP_INFO_TXOPPS 0x00200000
+#define VHT_CAP_INFO_HTCVHT 0x00400000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000
+#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000
+#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26
+
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff
+#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0
+
+#define VHT_CAP_MCS_MAP_0_7 0
+#define VHT_CAP_MCS_MAP_0_8 1
+#define VHT_CAP_MCS_MAP_0_9 2
+#define VHT_CAP_MCS_MAP_NONE 3
+#define VHT_CAP_MCS_MAP_S 2
+#define VHT_CAP_MCS_MAP_M 0x3
+
+#define VHT_CAP_MCS_MAP_NONE_ALL 0xffff
+
+#define VHT_CAP_MCS_MAP_0_9_NSS3 \
+ ((VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(1)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(2)) | \
+ (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(3)))
+
+#define VHT_CAP_MCS_MAP_NSS_MAX 8
+
+#define VHT_CAP_MCS_MAP_CREATE(mcsmap, nss, mcs) \
+ do { \
+ int i; \
+ for (i = 1; i <= nss; i++) { \
+ VHT_MCS_MAP_SET_MCS_PER_SS(i, mcs, mcsmap); \
+ } \
+ } while (0)
+
+#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \
+ ((mcs_code == VHT_CAP_MCS_MAP_0_7) ? 0xff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_8) ? 0x1ff : \
+ (mcs_code == VHT_CAP_MCS_MAP_0_9) ? 0x3ff : 0)
+
+#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \
+ ((mcs_map == 0xff) ? VHT_CAP_MCS_MAP_0_7 : \
+ (mcs_map == 0x1ff) ? VHT_CAP_MCS_MAP_0_8 : \
+ (mcs_map == 0x3ff) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE)
+
+typedef enum vht_cap_chan_width {
+ VHT_CAP_CHAN_WIDTH_SUPPORT_MANDATORY = 0x00,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160 = 0x04,
+ VHT_CAP_CHAN_WIDTH_SUPPORT_160_8080 = 0x08
+} vht_cap_chan_width_t;
+
+typedef enum vht_cap_max_mpdu_len {
+ VHT_CAP_MPDU_MAX_4K = 0x00,
+ VHT_CAP_MPDU_MAX_8K = 0x01,
+ VHT_CAP_MPDU_MAX_11K = 0x02
+} vht_cap_max_mpdu_len_t;
+
+#define VHT_MPDU_LIMIT_4K 3895
+#define VHT_MPDU_LIMIT_8K 7991
+#define VHT_MPDU_LIMIT_11K 11454
+
+BWL_PRE_PACKED_STRUCT struct vht_op_ie {
+ uint8 chan_width;
+ uint8 chan1;
+ uint8 chan2;
+ uint16 supp_mcs;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_op_ie vht_op_ie_t;
+
+#define VHT_OP_IE_LEN 5
+
+typedef enum vht_op_chan_width {
+ VHT_OP_CHAN_WIDTH_20_40 = 0,
+ VHT_OP_CHAN_WIDTH_80 = 1,
+ VHT_OP_CHAN_WIDTH_160 = 2,
+ VHT_OP_CHAN_WIDTH_80_80 = 3
+} vht_op_chan_width_t;
+
+#define AID_IE_LEN 2
+
+#define VHT_FEATURES_IE_TYPE 0x4
+BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr {
+ uint8 oui[3];
+ uint8 type;
+ uint8 rate_mask;
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_features_ie_hdr vht_features_ie_hdr_t;
+
+#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1) * VHT_CAP_MCS_MAP_S)
+#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \
+ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & VHT_CAP_MCS_MAP_M)
+#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \
+ do { \
+ (mcsMap) &= (~(VHT_CAP_MCS_MAP_M << VHT_MCS_MAP_GET_SS_IDX(nss))); \
+ (mcsMap) |= (((numMcs) & VHT_CAP_MCS_MAP_M) << VHT_MCS_MAP_GET_SS_IDX(nss)); \
+ } while (0)
+#define VHT_MCS_SS_SUPPORTED(nss, mcsMap) \
+ (VHT_MCS_MAP_GET_MCS_PER_SS((nss), (mcsMap)) != VHT_CAP_MCS_MAP_NONE)
+
+#define WPA_OUI "\x00\x50\xF2"
+#define WPA_OUI_LEN 3
+#define WPA_OUI_TYPE 1
+#define WPA_VERSION 1
+#define WPA2_OUI "\x00\x0F\xAC"
+#define WPA2_OUI_LEN 3
+#define WPA2_VERSION 1
+#define WPA2_VERSION_LEN 2
+
+#define WPS_OUI "\x00\x50\xF2"
+#define WPS_OUI_LEN 3
+#define WPS_OUI_TYPE 4
+
+#define WFA_OUI "\x50\x6F\x9A"
+#define WFA_OUI_LEN 3
+#define WFA_OUI_TYPE_P2P 9
+
+#define WFA_OUI_TYPE_TPC 8
+
+#define RSN_AKM_NONE 0
+#define RSN_AKM_UNSPECIFIED 1
+#define RSN_AKM_PSK 2
+#define RSN_AKM_FBT_1X 3
+#define RSN_AKM_FBT_PSK 4
+#define RSN_AKM_MFP_1X 5
+#define RSN_AKM_MFP_PSK 6
+#define RSN_AKM_TPK 7
+
+#define DOT11_MAX_DEFAULT_KEYS 4
+#define DOT11_MAX_KEY_SIZE 32
+#define DOT11_MAX_IV_SIZE 16
+#define DOT11_EXT_IV_FLAG (1<<5)
+#define DOT11_WPA_KEY_RSC_LEN 8
+
+#define WEP1_KEY_SIZE 5
+#define WEP1_KEY_HEX_SIZE 10
+#define WEP128_KEY_SIZE 13
+#define WEP128_KEY_HEX_SIZE 26
+#define TKIP_MIC_SIZE 8
+#define TKIP_EOM_SIZE 7
+#define TKIP_EOM_FLAG 0x5a
+#define TKIP_KEY_SIZE 32
+#define TKIP_MIC_AUTH_TX 16
+#define TKIP_MIC_AUTH_RX 24
+#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX
+#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX
+#define AES_KEY_SIZE 16
+#define AES_MIC_SIZE 8
+#define BIP_KEY_SIZE 16
+#define BIP_MIC_SIZE 8
+
+#define WCN_OUI "\x00\x50\xf2"
+#define WCN_TYPE 4
+
+BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mdid;
+ uint8 cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_mdid_ie dot11_mdid_ie_t;
+
+#define FBT_MDID_CAP_OVERDS 0x01
+#define FBT_MDID_CAP_RRP 0x02
+
+BWL_PRE_PACKED_STRUCT struct dot11_ft_ie {
+ uint8 id;
+ uint8 len;
+ uint16 mic_control;
+ uint8 mic[16];
+ uint8 anonce[32];
+ uint8 snonce[32];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_ie dot11_ft_ie_t;
+
+#define TIE_TYPE_RESERVED 0
+#define TIE_TYPE_REASSOC_DEADLINE 1
+#define TIE_TYPE_KEY_LIEFTIME 2
+#define TIE_TYPE_ASSOC_COMEBACK 3
+BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie {
+ uint8 id;
+ uint8 len;
+ uint8 type;
+ uint32 value;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timeout_ie dot11_timeout_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie {
+ uint8 id;
+ uint8 len;
+ uint16 key_info;
+ uint8 key_len;
+ uint8 rsc[8];
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_gtk_ie dot11_gtk_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct mmic_ie {
+ uint8 id;
+ uint8 len;
+ uint16 key_id;
+ uint8 ipn[6];
+ uint8 mic[BIP_MIC_SIZE];
+} BWL_POST_PACKED_STRUCT;
+typedef struct mmic_ie mmic_ie_t;
+
+#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00"
+#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF"
+
+#define WMM_OUI "\x00\x50\xF2"
+#define WMM_OUI_LEN 3
+#define WMM_OUI_TYPE 2
+#define WMM_VERSION 1
+#define WMM_VERSION_LEN 1
+
+#define WMM_OUI_SUBTYPE_PARAMETER 1
+#define WMM_PARAMETER_IE_LEN 24
+
+BWL_PRE_PACKED_STRUCT struct link_id_ie {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ struct ether_addr tdls_init_mac;
+ struct ether_addr tdls_resp_mac;
+} BWL_POST_PACKED_STRUCT;
+typedef struct link_id_ie link_id_ie_t;
+#define TDLS_LINK_ID_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie {
+ uint8 id;
+ uint8 len;
+ uint32 offset;
+ uint32 interval;
+ uint32 awake_win_slots;
+ uint32 max_wake_win;
+ uint16 idle_cnt;
+} BWL_POST_PACKED_STRUCT;
+typedef struct wakeup_sch_ie wakeup_sch_ie_t;
+#define TDLS_WAKEUP_SCH_IE_LEN 18
+
+BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie {
+ uint8 id;
+ uint8 len;
+ uint16 switch_time;
+ uint16 switch_timeout;
+} BWL_POST_PACKED_STRUCT;
+typedef struct channel_switch_timing_ie channel_switch_timing_ie_t;
+#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4
+
+BWL_PRE_PACKED_STRUCT struct pti_control_ie {
+ uint8 id;
+ uint8 len;
+ uint8 tid;
+ uint16 seq_control;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pti_control_ie pti_control_ie_t;
+#define TDLS_PTI_CONTROL_IE_LEN 3
+
+BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie {
+ uint8 id;
+ uint8 len;
+ uint8 status;
+} BWL_POST_PACKED_STRUCT;
+typedef struct pu_buffer_status_ie pu_buffer_status_ie_t;
+#define TDLS_PU_BUFFER_STATUS_IE_LEN 1
+#define TDLS_PU_BUFFER_STATUS_AC_BK 1
+#define TDLS_PU_BUFFER_STATUS_AC_BE 2
+#define TDLS_PU_BUFFER_STATUS_AC_VI 4
+#define TDLS_PU_BUFFER_STATUS_AC_VO 8
+
+#define GAS_REQUEST_ACTION_FRAME 10
+#define GAS_RESPONSE_ACTION_FRAME 11
+#define GAS_COMEBACK_REQUEST_ACTION_FRAME 12
+#define GAS_COMEBACK_RESPONSE_ACTION_FRAME 13
+
+#define IW_ANT_MASK 0x0f
+#define IW_INTERNET_MASK 0x10
+#define IW_ASRA_MASK 0x20
+#define IW_ESR_MASK 0x40
+#define IW_UESA_MASK 0x80
+
+#define IW_ANT_PRIVATE_NETWORK 0
+#define IW_ANT_PRIVATE_NETWORK_WITH_GUEST 1
+#define IW_ANT_CHARGEABLE_PUBLIC_NETWORK 2
+#define IW_ANT_FREE_PUBLIC_NETWORK 3
+#define IW_ANT_PERSONAL_DEVICE_NETWORK 4
+#define IW_ANT_EMERGENCY_SERVICES_NETWORK 5
+#define IW_ANT_TEST_NETWORK 14
+#define IW_ANT_WILDCARD_NETWORK 15
+
+#define ADVP_ANQP_PROTOCOL_ID 0
+
+#define ADVP_QRL_MASK 0x7f
+#define ADVP_PAME_BI_MASK 0x80
+
+#define ADVP_QRL_REQUEST 0x00
+#define ADVP_QRL_RESPONSE 0x7f
+#define ADVP_PAME_BI_DEPENDENT 0x00
+#define ADVP_PAME_BI_INDEPENDENT ADVP_PAME_BI_MASK
+
+#define ANQP_ID_QUERY_LIST 256
+#define ANQP_ID_CAPABILITY_LIST 257
+#define ANQP_ID_VENUE_NAME_INFO 258
+#define ANQP_ID_EMERGENCY_CALL_NUMBER_INFO 259
+#define ANQP_ID_NETWORK_AUTHENTICATION_TYPE_INFO 260
+#define ANQP_ID_ROAMING_CONSORTIUM_LIST 261
+#define ANQP_ID_IP_ADDRESS_TYPE_AVAILABILITY_INFO 262
+#define ANQP_ID_NAI_REALM_LIST 263
+#define ANQP_ID_G3PP_CELLULAR_NETWORK_INFO 264
+#define ANQP_ID_AP_GEOSPATIAL_LOCATION 265
+#define ANQP_ID_AP_CIVIC_LOCATION 266
+#define ANQP_ID_AP_LOCATION_PUBLIC_ID_URI 267
+#define ANQP_ID_DOMAIN_NAME_LIST 268
+#define ANQP_ID_EMERGENCY_ALERT_ID_URI 269
+#define ANQP_ID_EMERGENCY_NAI 271
+#define ANQP_ID_VENDOR_SPECIFIC_LIST 56797
+
+#define ANQP_OUI_SUBTYPE 9
+
+#define VENUE_LANGUAGE_CODE_SIZE 3
+#define VENUE_NAME_SIZE 255
+
+#define VENUE_UNSPECIFIED 0
+#define VENUE_ASSEMBLY 1
+#define VENUE_BUSINESS 2
+#define VENUE_EDUCATIONAL 3
+#define VENUE_FACTORY 4
+#define VENUE_INSTITUTIONAL 5
+#define VENUE_MERCANTILE 6
+#define VENUE_RESIDENTIAL 7
+#define VENUE_STORAGE 8
+#define VENUE_UTILITY 9
+#define VENUE_VEHICULAR 10
+#define VENUE_OUTDOOR 11
+
+#define NATI_ACCEPTANCE_OF_TERMS_CONDITIONS 0
+#define NATI_ONLINE_ENROLLMENT_SUPPORTED 1
+#define NATI_HTTP_HTTPS_REDIRECTION 2
+#define NATI_DNS_REDIRECTION 3
+
+#define IPA_IPV6_SHIFT 0
+#define IPA_IPV6_MASK (0x03 << IPA_IPV6_SHIFT)
+#define IPA_IPV6_NOT_AVAILABLE 0x00
+#define IPA_IPV6_AVAILABLE 0x01
+#define IPA_IPV6_UNKNOWN_AVAILABILITY 0x02
+
+#define IPA_IPV4_SHIFT 2
+#define IPA_IPV4_MASK (0x3f << IPA_IPV4_SHIFT)
+#define IPA_IPV4_NOT_AVAILABLE 0x00
+#define IPA_IPV4_PUBLIC 0x01
+#define IPA_IPV4_PORT_RESTRICT 0x02
+#define IPA_IPV4_SINGLE_NAT 0x03
+#define IPA_IPV4_DOUBLE_NAT 0x04
+#define IPA_IPV4_PORT_RESTRICT_SINGLE_NAT 0x05
+#define IPA_IPV4_PORT_RESTRICT_DOUBLE_NAT 0x06
+#define IPA_IPV4_UNKNOWN_AVAILABILITY 0x07
+
+#define REALM_ENCODING_RFC4282 0
+#define REALM_ENCODING_UTF8 1
+
+#define REALM_EAP_TLS 13
+#define REALM_EAP_SIM 18
+#define REALM_EAP_TTLS 21
+#define REALM_EAP_AKA 23
+#define REALM_EAP_PSK 47
+#define REALM_EAP_AKAP 50
+
+#define REALM_EXPANDED_EAP 1
+#define REALM_NON_EAP_INNER_AUTHENTICATION 2
+#define REALM_INNER_AUTHENTICATION_EAP 3
+#define REALM_EXPANDED_INNER_EAP 4
+#define REALM_CREDENTIAL 5
+#define REALM_TUNNELED_EAP_CREDENTIAL 6
+#define REALM_VENDOR_SPECIFIC_EAP 221
+
+#define REALM_PAP 1
+#define REALM_CHAP 2
+#define REALM_MSCHAP 3
+#define REALM_MSCHAPV2 4
+
+#define REALM_SIM 1
+#define REALM_USIM 2
+#define REALM_NFC 3
+#define REALM_HARDWARE_TOKEN 4
+#define REALM_SOFTOKEN 5
+#define REALM_CERTIFICATE 6
+#define REALM_USERNAME_PASSWORD 7
+#define REALM_SERVER_SIDE 8
+
+#define G3PP_GUD_VERSION 0
+#define G3PP_PLMN_LIST_IE 0
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/802.1d.h b/src/common/include/proto/802.1d.h
new file mode 100644
index 0000000..b30912d
--- /dev/null
+++ b/src/common/include/proto/802.1d.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental types and constants relating to 802.1D
+ *
+ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $
+ */
+
+#ifndef _802_1_D_
+#define _802_1_D_
+
+#define PRIO_8021D_NONE 2
+#define PRIO_8021D_BK 1
+#define PRIO_8021D_BE 0
+#define PRIO_8021D_EE 3
+#define PRIO_8021D_CL 4
+#define PRIO_8021D_VI 5
+#define PRIO_8021D_VO 6
+#define PRIO_8021D_NC 7
+#define MAXPRIO 7
+#define NUMPRIO (MAXPRIO + 1)
+
+#define ALLPRIO -1
+
+#define PRIO2PREC(prio) \
+ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
+
+#endif
diff --git a/src/common/include/proto/bcmeth.h b/src/common/include/proto/bcmeth.h
new file mode 100644
index 0000000..55fef46
--- /dev/null
+++ b/src/common/include/proto/bcmeth.h
@@ -0,0 +1,62 @@
+/*
+ * Broadcom Ethernettype protocol definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <packed_section_start.h>
+
+#define BCMILCP_SUBTYPE_RATE 1
+#define BCMILCP_SUBTYPE_LINK 2
+#define BCMILCP_SUBTYPE_CSA 3
+#define BCMILCP_SUBTYPE_LARQ 4
+#define BCMILCP_SUBTYPE_VENDOR 5
+#define BCMILCP_SUBTYPE_FLH 17
+
+#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+#define BCMILCP_SUBTYPE_CERT 32770
+#define BCMILCP_SUBTYPE_SES 32771
+
+#define BCMILCP_BCM_SUBTYPE_RESERVED 0
+#define BCMILCP_BCM_SUBTYPE_EVENT 1
+#define BCMILCP_BCM_SUBTYPE_SES 2
+
+#define BCMILCP_BCM_SUBTYPE_DPT 4
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+
+typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
+{
+ uint16 subtype;
+ uint16 length;
+ uint8 version;
+ uint8 oui[3];
+
+ uint16 usr_subtype;
+} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/bcmevent.h b/src/common/include/proto/bcmevent.h
new file mode 100644
index 0000000..f7253c0
--- /dev/null
+++ b/src/common/include/proto/bcmevent.h
@@ -0,0 +1,343 @@
+/*
+ * Broadcom Event protocol definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * $Id: bcmevent.h 382794 2013-02-04 17:34:08Z $
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <proto/bcmeth.h>
+
+#include <packed_section_start.h>
+
+#define BCM_EVENT_MSG_VERSION 2
+#define BCM_MSG_IFNAME_MAX 16
+
+#define WLC_EVENT_MSG_LINK 0x01
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02
+#define WLC_EVENT_MSG_GROUP 0x04
+#define WLC_EVENT_MSG_UNKBSS 0x08
+#define WLC_EVENT_MSG_UNKIF 0x10
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags;
+ uint32 event_type;
+ uint32 status;
+ uint32 reason;
+ uint32 auth_type;
+ uint32 datalen;
+ struct ether_addr addr;
+ char ifname[BCM_MSG_IFNAME_MAX];
+} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint16 version;
+ uint16 flags;
+ uint32 event_type;
+ uint32 status;
+ uint32 reason;
+ uint32 auth_type;
+ uint32 datalen;
+ struct ether_addr addr;
+ char ifname[BCM_MSG_IFNAME_MAX];
+ uint8 ifidx;
+ uint8 bsscfgidx;
+} BWL_POST_PACKED_STRUCT wl_event_msg_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
+ struct ether_header eth;
+ bcmeth_hdr_t bcm_hdr;
+ wl_event_msg_t event;
+
+} BWL_POST_PACKED_STRUCT bcm_event_t;
+
+#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+#define WLC_E_SET_SSID 0
+#define WLC_E_JOIN 1
+#define WLC_E_START 2
+#define WLC_E_AUTH 3
+#define WLC_E_AUTH_IND 4
+#define WLC_E_DEAUTH 5
+#define WLC_E_DEAUTH_IND 6
+#define WLC_E_ASSOC 7
+#define WLC_E_ASSOC_IND 8
+#define WLC_E_REASSOC 9
+#define WLC_E_REASSOC_IND 10
+#define WLC_E_DISASSOC 11
+#define WLC_E_DISASSOC_IND 12
+#define WLC_E_QUIET_START 13
+#define WLC_E_QUIET_END 14
+#define WLC_E_BEACON_RX 15
+#define WLC_E_LINK 16
+#define WLC_E_MIC_ERROR 17
+#define WLC_E_NDIS_LINK 18
+#define WLC_E_ROAM 19
+#define WLC_E_TXFAIL 20
+#define WLC_E_PMKID_CACHE 21
+#define WLC_E_RETROGRADE_TSF 22
+#define WLC_E_PRUNE 23
+#define WLC_E_AUTOAUTH 24
+#define WLC_E_EAPOL_MSG 25
+#define WLC_E_SCAN_COMPLETE 26
+#define WLC_E_ADDTS_IND 27
+#define WLC_E_DELTS_IND 28
+#define WLC_E_BCNSENT_IND 29
+#define WLC_E_BCNRX_MSG 30
+#define WLC_E_BCNLOST_MSG 31
+#define WLC_E_ROAM_PREP 32
+#define WLC_E_PFN_NET_FOUND 33
+#define WLC_E_PFN_NET_LOST 34
+#define WLC_E_RESET_COMPLETE 35
+#define WLC_E_JOIN_START 36
+#define WLC_E_ROAM_START 37
+#define WLC_E_ASSOC_START 38
+#define WLC_E_IBSS_ASSOC 39
+#define WLC_E_RADIO 40
+#define WLC_E_PSM_WATCHDOG 41
+#define WLC_E_PROBREQ_MSG 44
+#define WLC_E_SCAN_CONFIRM_IND 45
+#define WLC_E_PSK_SUP 46
+#define WLC_E_COUNTRY_CODE_CHANGED 47
+#define WLC_E_EXCEEDED_MEDIUM_TIME 48
+#define WLC_E_ICV_ERROR 49
+#define WLC_E_UNICAST_DECODE_ERROR 50
+#define WLC_E_MULTICAST_DECODE_ERROR 51
+#define WLC_E_TRACE 52
+#define WLC_E_IF 54
+#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55
+#define WLC_E_RSSI 56
+#define WLC_E_PFN_SCAN_COMPLETE 57
+#define WLC_E_EXTLOG_MSG 58
+#define WLC_E_ACTION_FRAME 59
+#define WLC_E_ACTION_FRAME_COMPLETE 60
+#define WLC_E_PRE_ASSOC_IND 61
+#define WLC_E_PRE_REASSOC_IND 62
+#define WLC_E_CHANNEL_ADOPTED 63
+#define WLC_E_AP_STARTED 64
+#define WLC_E_DFS_AP_STOP 65
+#define WLC_E_DFS_AP_RESUME 66
+#define WLC_E_WAI_STA_EVENT 67
+#define WLC_E_WAI_MSG 68
+#define WLC_E_ESCAN_RESULT 69
+#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
+#define WLC_E_PROBRESP_MSG 71
+#define WLC_E_P2P_PROBREQ_MSG 72
+#define WLC_E_DCS_REQUEST 73
+
+#define WLC_E_FIFO_CREDIT_MAP 74
+
+#define WLC_E_ACTION_FRAME_RX 75
+#define WLC_E_WAKE_EVENT 76
+#define WLC_E_RM_COMPLETE 77
+#define WLC_E_HTSFSYNC 78
+#define WLC_E_OVERLAY_REQ 79
+#define WLC_E_CSA_COMPLETE_IND 80
+#define WLC_E_EXCESS_PM_WAKE_EVENT 81
+#define WLC_E_PFN_SCAN_NONE 82
+#define WLC_E_PFN_SCAN_ALLGONE 83
+#define WLC_E_GTK_PLUMBED 84
+#define WLC_E_ASSOC_IND_NDIS 85
+#define WLC_E_REASSOC_IND_NDIS 86
+#define WLC_E_ASSOC_REQ_IE 87
+#define WLC_E_ASSOC_RESP_IE 88
+#define WLC_E_ASSOC_RECREATED 89
+#define WLC_E_ACTION_FRAME_RX_NDIS 90
+#define WLC_E_AUTH_REQ 91
+#define WLC_E_TDLS_PEER_EVENT 92
+#define WLC_E_SPEEDY_RECREATE_FAIL 93
+#define WLC_E_NATIVE 94
+#define WLC_E_PKTDELAY_IND 95
+#define WLC_E_IBSS_COALESCE 96
+#define WLC_E_SERVICE_FOUND 102
+#define WLC_E_GAS_FRAGMENT_RX 103
+#define WLC_E_GAS_COMPLETE 104
+#define WLC_E_P2PO_ADD_DEVICE 105
+#define WLC_E_P2PO_DEL_DEVICE 106
+#define WLC_E_WNM_STA_SLEEP 107
+#define WLC_E_NONE 108
+#define WLC_E_PROXD 109
+#define WLC_E_AWDL_AW_EXT_END 111
+#define WLC_E_AWDL_AW_EXT_START 112
+#define WLC_E_AWDL_AW_START 113
+#define WLC_E_AWDL_RADIO_OFF 114
+#define WLC_E_AWDL_PEER_STATE 115
+#define WLC_E_AWDL_SYNC_STATE_CHANGED 116
+#define WLC_E_AWDL_CHIP_RESET 117
+#define WLC_E_AWDL_INTERLEAVED_SCAN_START 118
+#define WLC_E_AWDL_INTERLEAVED_SCAN_STOP 119
+#define WLC_E_AWDL_PEER_CACHE_CONTROL 120
+#define WLC_E_CSA_START_IND 121
+#define WLC_E_CSA_DONE_IND 122
+#define WLC_E_CSA_FAILURE_IND 123
+#define WLC_E_LAST 124
+
+typedef struct {
+ uint event;
+ const char *name;
+} bcmevent_name_t;
+
+extern const bcmevent_name_t bcmevent_names[];
+extern const int bcmevent_names_size;
+
+#define WLC_E_STATUS_SUCCESS 0
+#define WLC_E_STATUS_FAIL 1
+#define WLC_E_STATUS_TIMEOUT 2
+#define WLC_E_STATUS_NO_NETWORKS 3
+#define WLC_E_STATUS_ABORT 4
+#define WLC_E_STATUS_NO_ACK 5
+#define WLC_E_STATUS_UNSOLICITED 6
+#define WLC_E_STATUS_ATTEMPT 7
+#define WLC_E_STATUS_PARTIAL 8
+#define WLC_E_STATUS_NEWSCAN 9
+#define WLC_E_STATUS_NEWASSOC 10
+#define WLC_E_STATUS_11HQUIET 11
+#define WLC_E_STATUS_SUPPRESS 12
+#define WLC_E_STATUS_NOCHANS 13
+#define WLC_E_STATUS_CS_ABORT 15
+#define WLC_E_STATUS_ERROR 16
+
+#define WLC_E_REASON_INITIAL_ASSOC 0
+#define WLC_E_REASON_LOW_RSSI 1
+#define WLC_E_REASON_DEAUTH 2
+#define WLC_E_REASON_DISASSOC 3
+#define WLC_E_REASON_BCNS_LOST 4
+#define WLC_E_REASON_MINTXRATE 9
+#define WLC_E_REASON_TXFAIL 10
+
+#define WLC_E_REASON_FAST_ROAM_FAILED 5
+#define WLC_E_REASON_DIRECTED_ROAM 6
+#define WLC_E_REASON_TSPEC_REJECTED 7
+#define WLC_E_REASON_BETTER_AP 8
+
+#define WLC_E_REASON_REQUESTED_ROAM 11
+
+#define WLC_E_PRUNE_ENCR_MISMATCH 1
+#define WLC_E_PRUNE_BCAST_BSSID 2
+#define WLC_E_PRUNE_MAC_DENY 3
+#define WLC_E_PRUNE_MAC_NA 4
+#define WLC_E_PRUNE_REG_PASSV 5
+#define WLC_E_PRUNE_SPCT_MGMT 6
+#define WLC_E_PRUNE_RADAR 7
+#define WLC_E_RSN_MISMATCH 8
+#define WLC_E_PRUNE_NO_COMMON_RATES 9
+#define WLC_E_PRUNE_BASIC_RATES 10
+#define WLC_E_PRUNE_CIPHER_NA 12
+#define WLC_E_PRUNE_KNOWN_STA 13
+#define WLC_E_PRUNE_WDS_PEER 15
+#define WLC_E_PRUNE_QBSS_LOAD 16
+#define WLC_E_PRUNE_HOME_AP 17
+
+#define WLC_E_SUP_OTHER 0
+#define WLC_E_SUP_DECRYPT_KEY_DATA 1
+#define WLC_E_SUP_BAD_UCAST_WEP128 2
+#define WLC_E_SUP_BAD_UCAST_WEP40 3
+#define WLC_E_SUP_UNSUP_KEY_LEN 4
+#define WLC_E_SUP_PW_KEY_CIPHER 5
+#define WLC_E_SUP_MSG3_TOO_MANY_IE 6
+#define WLC_E_SUP_MSG3_IE_MISMATCH 7
+#define WLC_E_SUP_NO_INSTALL_FLAG 8
+#define WLC_E_SUP_MSG3_NO_GTK 9
+#define WLC_E_SUP_GRP_KEY_CIPHER 10
+#define WLC_E_SUP_GRP_MSG1_NO_GTK 11
+#define WLC_E_SUP_GTK_DECRYPT_FAIL 12
+#define WLC_E_SUP_SEND_FAIL 13
+#define WLC_E_SUP_DEAUTH 14
+#define WLC_E_SUP_WPA_PSK_TMO 15
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data {
+ uint16 version;
+ uint16 channel;
+ int32 rssi;
+ uint32 mactime;
+ uint32 rate;
+} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t;
+
+#define BCM_RX_FRAME_DATA_VERSION 1
+
+typedef struct wl_event_data_if {
+ uint8 ifidx;
+ uint8 opcode;
+ uint8 reserved;
+ uint8 bssidx;
+ uint8 role;
+} wl_event_data_if_t;
+
+#define WLC_E_IF_ADD 1
+#define WLC_E_IF_DEL 2
+#define WLC_E_IF_CHANGE 3
+
+#define WLC_E_IF_FLAGS_BSSCFG_NOIF 0x1
+
+#define WLC_E_IF_ROLE_STA 0
+#define WLC_E_IF_ROLE_AP 1
+#define WLC_E_IF_ROLE_WDS 2
+#define WLC_E_IF_ROLE_P2P_GO 3
+#define WLC_E_IF_ROLE_P2P_CLIENT 4
+
+#define WLC_E_LINK_BCN_LOSS 1
+#define WLC_E_LINK_DISASSOC 2
+#define WLC_E_LINK_ASSOC_REC 3
+#define WLC_E_LINK_BSSCFG_DIS 4
+
+#define WLC_E_OVL_DOWNLOAD 0
+#define WLC_E_OVL_UPDATE_IND 1
+
+#define WLC_E_TDLS_PEER_DISCOVERED 0
+#define WLC_E_TDLS_PEER_CONNECTED 1
+#define WLC_E_TDLS_PEER_DISCONNECTED 2
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas {
+ uint16 channel;
+ uint8 dialog_token;
+ uint8 fragment_id;
+ uint16 status_code;
+ uint16 data_len;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT wl_event_gas_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv {
+ uint16 length;
+ uint8 protocol;
+ uint8 transaction_id;
+ uint8 status_code;
+ uint8 data[1];
+} BWL_POST_PACKED_STRUCT wl_sd_tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd {
+ uint16 channel;
+ uint8 count;
+ wl_sd_tlv_t tlv[1];
+} BWL_POST_PACKED_STRUCT wl_event_sd_t;
+
+#define WLC_E_PROXD_FOUND 1
+#define WLC_E_PROXD_GONE 2
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/bcmip.h b/src/common/include/proto/bcmip.h
new file mode 100644
index 0000000..50ce97d
--- /dev/null
+++ b/src/common/include/proto/bcmip.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Fundamental constants relating to IP Protocol
+ *
+ * $Id: bcmip.h 329791 2012-04-26 22:36:58Z $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+#include <packed_section_start.h>
+
+#define IP_VER_OFFSET 0x0
+#define IP_VER_MASK 0xf0
+#define IP_VER_SHIFT 4
+#define IP_VER_4 4
+#define IP_VER_6 6
+
+#define IP_VER(ip_body) \
+ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP 0x1
+#define IP_PROT_IGMP 0x2
+#define IP_PROT_TCP 0x6
+#define IP_PROT_UDP 0x11
+#define IP_PROT_ICMP6 0x3a
+
+#define IPV4_VER_HL_OFFSET 0
+#define IPV4_TOS_OFFSET 1
+#define IPV4_PKTLEN_OFFSET 2
+#define IPV4_PKTFLAG_OFFSET 6
+#define IPV4_PROT_OFFSET 9
+#define IPV4_CHKSUM_OFFSET 10
+#define IPV4_SRC_IP_OFFSET 12
+#define IPV4_DEST_IP_OFFSET 16
+#define IPV4_OPTIONS_OFFSET 20
+#define IPV4_MIN_HEADER_LEN 20
+
+#define IPV4_VER_MASK 0xf0
+#define IPV4_VER_SHIFT 4
+
+#define IPV4_HLEN_MASK 0x0f
+#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN 4
+
+#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \
+ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0)
+
+#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \
+ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff)
+
+#define IPV4_TOS_DSCP_MASK 0xfc
+#define IPV4_TOS_DSCP_SHIFT 2
+
+#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define IPV4_TOS_PREC_MASK 0xe0
+#define IPV4_TOS_PREC_SHIFT 5
+
+#define IPV4_TOS_LOWDELAY 0x10
+#define IPV4_TOS_THROUGHPUT 0x8
+#define IPV4_TOS_RELIABILITY 0x4
+
+#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_FRAG_RESV 0x8000
+#define IPV4_FRAG_DONT 0x4000
+#define IPV4_FRAG_MORE 0x2000
+#define IPV4_FRAG_OFFSET_MASK 0x1fff
+
+#define IPV4_ADDR_STR_LEN 16
+
+BWL_PRE_PACKED_STRUCT struct ipv4_addr {
+ uint8 addr[IPV4_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv4_hdr {
+ uint8 version_ihl;
+ uint8 tos;
+ uint16 tot_len;
+ uint16 id;
+ uint16 frag;
+ uint8 ttl;
+ uint8 prot;
+ uint16 hdr_chksum;
+ uint8 src_ip[IPV4_ADDR_LEN];
+ uint8 dst_ip[IPV4_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+#define IPV6_PAYLOAD_LEN_OFFSET 4
+#define IPV6_NEXT_HDR_OFFSET 6
+#define IPV6_HOP_LIMIT_OFFSET 7
+#define IPV6_SRC_IP_OFFSET 8
+#define IPV6_DEST_IP_OFFSET 24
+
+#define IPV6_TRAFFIC_CLASS(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \
+ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4))
+
+#define IPV6_FLOW_LABEL(ipv6_body) \
+ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \
+ (((uint8 *)(ipv6_body))[2] << 8) | \
+ (((uint8 *)(ipv6_body))[3]))
+
+#define IPV6_PAYLOAD_LEN(ipv6_body) \
+ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \
+ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1])
+
+#define IPV6_NEXT_HDR(ipv6_body) \
+ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET])
+
+#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body)
+
+#define IPV6_ADDR_LEN 16
+
+#define IP_TOS46(ip_body) \
+ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \
+ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0)
+
+#define IPV6_EXTHDR_HOP 0
+#define IPV6_EXTHDR_ROUTING 43
+#define IPV6_EXTHDR_FRAGMENT 44
+#define IPV6_EXTHDR_AUTH 51
+#define IPV6_EXTHDR_NONE 59
+#define IPV6_EXTHDR_DEST 60
+
+#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \
+ ((prot) == IPV6_EXTHDR_ROUTING) || \
+ ((prot) == IPV6_EXTHDR_FRAGMENT) || \
+ ((prot) == IPV6_EXTHDR_AUTH) || \
+ ((prot) == IPV6_EXTHDR_NONE) || \
+ ((prot) == IPV6_EXTHDR_DEST))
+
+#define IPV6_MIN_HLEN 40
+
+#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3)
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr {
+ uint8 nexthdr;
+ uint8 hdrlen;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag {
+ uint8 nexthdr;
+ uint8 rsvd;
+ uint16 frag_off;
+ uint32 ident;
+} BWL_POST_PACKED_STRUCT;
+
+static INLINE int32
+ipv6_exthdr_len(uint8 *h, uint8 *proto)
+{
+ uint16 len = 0, hlen;
+ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h;
+
+ while (IPV6_EXTHDR(eh->nexthdr)) {
+ if (eh->nexthdr == IPV6_EXTHDR_NONE)
+ return -1;
+ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT)
+ hlen = 8;
+ else if (eh->nexthdr == IPV6_EXTHDR_AUTH)
+ hlen = (eh->hdrlen + 2) << 2;
+ else
+ hlen = IPV6_EXTHDR_LEN(eh);
+
+ len += hlen;
+ eh = (struct ipv6_exthdr *)(h + len);
+ }
+
+ *proto = eh->nexthdr;
+ return len;
+}
+
+#define IPV4_ISMULTI(a) (((a) & 0xf0000000) == 0xe0000000)
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/ethernet.h b/src/common/include/proto/ethernet.h
new file mode 100644
index 0000000..09315c9
--- /dev/null
+++ b/src/common/include/proto/ethernet.h
@@ -0,0 +1,156 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: ethernet.h 370577 2012-11-22 07:55:21Z $
+ */
+
+#ifndef _NET_ETHERNET_H_
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+#include <packed_section_start.h>
+
+#define ETHER_ADDR_LEN 6
+
+#define ETHER_TYPE_LEN 2
+
+#define ETHER_CRC_LEN 4
+
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+
+#define ETHER_MIN_LEN 64
+
+#define ETHER_MIN_DATA 46
+
+#define ETHER_MAX_LEN 1518
+
+#define ETHER_MAX_DATA 1500
+
+#define ETHER_TYPE_MIN 0x0600
+#define ETHER_TYPE_IP 0x0800
+#define ETHER_TYPE_ARP 0x0806
+#define ETHER_TYPE_8021Q 0x8100
+#define ETHER_TYPE_IPV6 0x86dd
+#define ETHER_TYPE_BRCM 0x886c
+#define ETHER_TYPE_802_1X 0x888e
+#define ETHER_TYPE_802_1X_PREAUTH 0x88c7
+#define ETHER_TYPE_WAI 0x88b4
+#define ETHER_TYPE_89_0D 0x890d
+
+#define ETHER_TYPE_PPP_SES 0x8864
+
+#define ETHER_TYPE_IPV6 0x86dd
+
+#define ETHER_BRCM_SUBTYPE_LEN 4
+
+#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN)
+#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN)
+#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN)
+
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \
+ ((uint8 *)ea)[0] = 0x01; \
+ ((uint8 *)ea)[1] = 0x00; \
+ ((uint8 *)ea)[2] = 0x5e; \
+ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \
+ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \
+ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \
+}
+
+#ifndef __INCif_etherh
+
+BWL_PRE_PACKED_STRUCT struct ether_header {
+ uint8 ether_dhost[ETHER_ADDR_LEN];
+ uint8 ether_shost[ETHER_ADDR_LEN];
+ uint16 ether_type;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+#endif
+
+#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2))
+#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2)
+#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd))
+#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2))
+
+#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
+
+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
+
+#define eacmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \
+ (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \
+ (((const uint16 *)(a))[2] ^ ((const uint16 *)(b))[2]))
+
+#define ether_cmp(a, b) eacmp(a, b)
+
+#define eacopy(s, d) \
+do { \
+ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \
+ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \
+ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \
+} while (0)
+
+#define ether_copy(s, d) eacopy(s, d)
+
+#define ether_rcopy(s, d) \
+do { \
+ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \
+ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \
+ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \
+} while (0)
+
+static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
+static const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}};
+
+#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \
+ ((const uint8 *)(ea))[1] & \
+ ((const uint8 *)(ea))[2] & \
+ ((const uint8 *)(ea))[3] & \
+ ((const uint8 *)(ea))[4] & \
+ ((const uint8 *)(ea))[5]) == 0xff)
+#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \
+ ((const uint8 *)(ea))[1] | \
+ ((const uint8 *)(ea))[2] | \
+ ((const uint8 *)(ea))[3] | \
+ ((const uint8 *)(ea))[4] | \
+ ((const uint8 *)(ea))[5]) == 0)
+
+#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \
+ ((const uint16 *)(da))[1] | \
+ ((const uint16 *)(da))[2]) == 0)
+#define ETHER_ISNULLSRC(sa) ETHER_ISNULLDEST(sa)
+
+#define ETHER_MOVE_HDR(d, s) \
+do { \
+ struct ether_header t; \
+ t = *(struct ether_header *)(s); \
+ *(struct ether_header *)(d) = t; \
+} while (0)
+
+#define ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0)
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/common/include/proto/ieee80211_radiotap.h b/src/common/include/proto/ieee80211_radiotap.h
new file mode 100644
index 0000000..d3945b8
--- /dev/null
+++ b/src/common/include/proto/ieee80211_radiotap.h
@@ -0,0 +1,161 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.11 2007/12/13 01:23:40 sam Exp $ */
+
+#ifndef _NET80211_IEEE80211_RADIOTAP_H_
+#define _NET80211_IEEE80211_RADIOTAP_H_
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+#ifndef DLT_IEEE802_11_RADIO
+#define DLT_IEEE802_11_RADIO 127
+#endif
+#endif
+
+#define IEEE80211_RADIOTAP_HDRLEN 64
+
+struct ieee80211_radiotap_header {
+ uint8_t it_version;
+ uint8_t it_pad;
+ uint16_t it_len;
+ uint32_t it_present;
+} __attribute__((packed));
+
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+
+ IEEE80211_RADIOTAP_TXFLAGS = 15,
+ IEEE80211_RADIOTAP_RETRIES = 17,
+ IEEE80211_RADIOTAP_XCHANNEL = 18,
+ IEEE80211_RADIOTAP_MCS = 19,
+ IEEE80211_RADIOTAP_AMPDU = 20,
+ IEEE80211_RADIOTAP_VHT = 21,
+ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
+ IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
+ IEEE80211_RADIOTAP_EXT = 31,
+ };
+
+#ifndef _KERNEL
+
+#define IEEE80211_CHAN_TURBO 0x00000010
+#define IEEE80211_CHAN_CCK 0x00000020
+#define IEEE80211_CHAN_OFDM 0x00000040
+#define IEEE80211_CHAN_2GHZ 0x00000080
+#define IEEE80211_CHAN_5GHZ 0x00000100
+#define IEEE80211_CHAN_PASSIVE 0x00000200
+#define IEEE80211_CHAN_DYN 0x00000400
+#define IEEE80211_CHAN_GFSK 0x00000800
+#define IEEE80211_CHAN_GSM 0x00001000
+#define IEEE80211_CHAN_STURBO 0x00002000
+#define IEEE80211_CHAN_HALF 0x00004000
+#define IEEE80211_CHAN_QUARTER 0x00008000
+#define IEEE80211_CHAN_HT20 0x00010000
+#define IEEE80211_CHAN_HT40U 0x00020000
+#define IEEE80211_CHAN_HT40D 0x00040000
+#endif
+
+#define IEEE80211_RADIOTAP_F_CFP 0x01
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02
+#define IEEE80211_RADIOTAP_F_WEP 0x04
+#define IEEE80211_RADIOTAP_F_FRAG 0x08
+#define IEEE80211_RADIOTAP_F_FCS 0x10
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x20
+#define IEEE80211_RADIOTAP_F_BADFCS 0x40
+
+#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
+#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
+#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
+#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
+#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
+#define IEEE80211_RADIOTAP_MCS_BW_20 0
+#define IEEE80211_RADIOTAP_MCS_BW_40 1
+#define IEEE80211_RADIOTAP_MCS_BW_20L 2
+#define IEEE80211_RADIOTAP_MCS_BW_20U 3
+#define IEEE80211_RADIOTAP_MCS_SGI 0x04
+#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
+#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_80 0x20
+#define IEEE80211_RADIOTAP_MCS_BW_20LL 0x40
+#define IEEE80211_RADIOTAP_MCS_BW_20LU 0x60
+#define IEEE80211_RADIOTAP_MCS_BW_20UL 0x80
+#define IEEE80211_RADIOTAP_MCS_BW_20UU 0xa0
+#define IEEE80211_RADIOTAP_MCS_BW_40L 0xc0
+#define IEEE80211_RADIOTAP_MCS_BW_40U 0xe0
+
+#define IEEE80211_RADIOTAP_VHT_HAVE_STBC 0x0001
+#define IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS 0x0002
+#define IEEE80211_RADIOTAP_VHT_HAVE_GI 0x0004
+#define IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA 0x0008
+#define IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA 0x0010
+#define IEEE80211_RADIOTAP_VHT_HAVE_BF 0x0020
+#define IEEE80211_RADIOTAP_VHT_HAVE_BW 0x0040
+#define IEEE80211_RADIOTAP_VHT_HAVE_GID 0x0080
+#define IEEE80211_RADIOTAP_VHT_HAVE_PAID 0x0100
+
+#define IEEE80211_RADIOTAP_VHT_STBC 0x01
+#define IEEE80211_RADIOTAP_VHT_TXOP_PS 0x02
+#define IEEE80211_RADIOTAP_VHT_SGI 0x04
+#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA 0x08
+#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA 0x10
+#define IEEE80211_RADIOTAP_VHT_BF 0x20
+
+#define IEEE80211_RADIOTAP_VHT_NSS 0x0f
+#define IEEE80211_RADIOTAP_VHT_MCS 0xf0
+
+#define IEEE80211_RADIOTAP_VHT_CODING_LDPC 0x01
+
+#define IEEE80211_RADIOTAP_VHT_BW_20 IEEE80211_RADIOTAP_MCS_BW_20
+#define IEEE80211_RADIOTAP_VHT_BW_40 IEEE80211_RADIOTAP_MCS_BW_40
+#define IEEE80211_RADIOTAP_VHT_BW_20L IEEE80211_RADIOTAP_MCS_BW_20L
+#define IEEE80211_RADIOTAP_VHT_BW_20U IEEE80211_RADIOTAP_MCS_BW_20U
+#define IEEE80211_RADIOTAP_VHT_BW_80 4
+#define IEEE80211_RADIOTAP_VHT_BW_40L 5
+#define IEEE80211_RADIOTAP_VHT_BW_40U 6
+#define IEEE80211_RADIOTAP_VHT_BW_20LL 7
+#define IEEE80211_RADIOTAP_VHT_BW_20LU 8
+#define IEEE80211_RADIOTAP_VHT_BW_20UL 9
+#define IEEE80211_RADIOTAP_VHT_BW_20UU 10
+#define IEEE80211_RADIOTAP_VHT_BW_160 11
+#define IEEE80211_RADIOTAP_VHT_BW_80L 12
+#define IEEE80211_RADIOTAP_VHT_BW_80U 13
+#define IEEE80211_RADIOTAP_VHT_BW_40LL 14
+#define IEEE80211_RADIOTAP_VHT_BW_40LU 15
+#define IEEE80211_RADIOTAP_VHT_BW_40UL 16
+#define IEEE80211_RADIOTAP_VHT_BW_40UU 17
+#define IEEE80211_RADIOTAP_VHT_BW_20LLL 18
+#define IEEE80211_RADIOTAP_VHT_BW_20LLU 19
+#define IEEE80211_RADIOTAP_VHT_BW_20LUL 20
+#define IEEE80211_RADIOTAP_VHT_BW_20LUU 21
+#define IEEE80211_RADIOTAP_VHT_BW_20ULL 22
+#define IEEE80211_RADIOTAP_VHT_BW_20ULU 23
+#define IEEE80211_RADIOTAP_VHT_BW_20UUL 24
+#define IEEE80211_RADIOTAP_VHT_BW_20UUU 25
+
+#define IEEE80211_RADIOTAP_TXF_FAIL 0x0001
+#define IEEE80211_RADIOTAP_TXF_CTS 0x0002
+#define IEEE80211_RADIOTAP_TXF_RTSCTS 0x0004
+#define IEEE80211_RADIOTAP_TXF_NOACK 0x0008
+#define IEEE80211_RADIOTAP_TXF_SEQOVR 0x0010
+
+#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
+#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
+#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
+#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
+#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
+#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
+#define IEEE80211_RADIOTAP_AMPDU_MPDU_ONLY 0x8000
+
+#endif
diff --git a/src/common/include/proto/wpa.h b/src/common/include/proto/wpa.h
new file mode 100644
index 0000000..19cfdf0
--- /dev/null
+++ b/src/common/include/proto/wpa.h
@@ -0,0 +1,148 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wpa.h 367468 2012-11-08 05:49:44Z $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+#include <packed_section_start.h>
+
+#define DOT11_RC_INVALID_WPA_IE 13
+#define DOT11_RC_MIC_FAILURE 14
+#define DOT11_RC_4WH_TIMEOUT 15
+#define DOT11_RC_GTK_UPDATE_TIMEOUT 16
+#define DOT11_RC_WPA_IE_MISMATCH 17
+#define DOT11_RC_INVALID_MC_CIPHER 18
+#define DOT11_RC_INVALID_UC_CIPHER 19
+#define DOT11_RC_INVALID_AKMP 20
+#define DOT11_RC_BAD_WPA_VERSION 21
+#define DOT11_RC_INVALID_WPA_CAP 22
+#define DOT11_RC_8021X_AUTH_FAIL 23
+
+#define WPA2_PMKID_LEN 16
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 tag;
+ uint8 length;
+ uint8 oui[3];
+ uint8 oui_type;
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version;
+} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t;
+#define WPA_IE_OUITYPE_LEN 4
+#define WPA_IE_FIXED_LEN 8
+#define WPA_IE_TAG_FIXED_LEN 6
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+ uint8 tag;
+ uint8 length;
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT version;
+} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t;
+#define WPA_RSN_IE_FIXED_LEN 4
+#define WPA_RSN_IE_TAG_FIXED_LEN 2
+typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN];
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ uint8 oui[3];
+ uint8 type;
+} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t;
+#define WPA_SUITE_LEN 4
+
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_suite_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t;
+#define WPA_IE_SUITE_COUNT_LEN 2
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+ BWL_PRE_PACKED_STRUCT struct {
+ uint8 low;
+ uint8 high;
+ } BWL_POST_PACKED_STRUCT count;
+ wpa_pmkid_t list[1];
+} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t;
+
+#define WPA_CIPHER_NONE 0
+#define WPA_CIPHER_WEP_40 1
+#define WPA_CIPHER_TKIP 2
+#define WPA_CIPHER_AES_OCB 3
+#define WPA_CIPHER_AES_CCM 4
+#define WPA_CIPHER_WEP_104 5
+#define WPA_CIPHER_BIP 6
+#define WPA_CIPHER_TPK 7
+
+#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \
+ (cipher) == WPA_CIPHER_WEP_40 || \
+ (cipher) == WPA_CIPHER_WEP_104 || \
+ (cipher) == WPA_CIPHER_TKIP || \
+ (cipher) == WPA_CIPHER_AES_OCB || \
+ (cipher) == WPA_CIPHER_AES_CCM || \
+ (cipher) == WPA_CIPHER_TPK)
+
+#define WPA_TKIP_CM_DETECT 60
+#define WPA_TKIP_CM_BLOCK 60
+
+#define RSN_CAP_LEN 2
+
+#define RSN_CAP_PREAUTH 0x0001
+#define RSN_CAP_NOPAIRWISE 0x0002
+#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
+#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2
+#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030
+#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4
+#define RSN_CAP_1_REPLAY_CNTR 0
+#define RSN_CAP_2_REPLAY_CNTRS 1
+#define RSN_CAP_4_REPLAY_CNTRS 2
+#define RSN_CAP_16_REPLAY_CNTRS 3
+#define RSN_CAP_MFPR 0x0040
+#define RSN_CAP_MFPC 0x0080
+#define RSN_CAP_SPPC 0x0400
+#define RSN_CAP_SPPR 0x0800
+
+#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
+#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT
+#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK
+
+#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1)
+
+#define WPA_CAP_LEN RSN_CAP_LEN
+#define WPA_PMKID_CNT_LEN 2
+
+#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH
+
+#define WPA2_PMKID_COUNT_LEN 2
+
+#include <packed_section_end.h>
+
+#endif
diff --git a/src/include/bcmcrypto/tkhash.h b/src/include/bcmcrypto/tkhash.h
new file mode 100644
index 0000000..6afc334
--- /dev/null
+++ b/src/include/bcmcrypto/tkhash.h
@@ -0,0 +1,33 @@
+/*
+ * tkhash.h
+ * Prototypes for TKIP hash functions.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: tkhash.h 458337 2014-02-26 18:39:26Z $
+ */
+
+#ifndef _TKHASH_H_
+#define _TKHASH_H_
+
+#include <typedefs.h>
+
+#define TKHASH_P1_KEY_SIZE 10
+#define TKHASH_P2_KEY_SIZE 16
+
+extern void BCMROMFN(tkhash_phase1)(uint16 *P1K, const uint8 *TK, const uint8 *TA, uint32 IV32);
+extern void BCMROMFN(tkhash_phase2)(uint8 *RC4KEY, const uint8 *TK, const uint16 *P1K, uint16 IV16);
+
+#endif
diff --git a/src/include/bcmdefs.h b/src/include/bcmdefs.h
new file mode 100644
index 0000000..413ce84
--- /dev/null
+++ b/src/include/bcmdefs.h
@@ -0,0 +1,164 @@
+/*
+ * Misc system wide definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmdefs.h 432150 2013-10-25 20:57:18Z $
+ */
+
+#ifndef _bcmdefs_h_
+#define _bcmdefs_h_
+
+#define BCM_REFERENCE(data) ((void)(data))
+
+#ifdef __GNUC__
+#define UNUSED_VAR __attribute__ ((unused))
+#else
+#define UNUSED_VAR
+#endif
+
+#define STATIC_ASSERT(expr) { \
+ \
+ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
+ \
+ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
+}
+
+#define bcmreclaimed 0
+#define BCMATTACHDATA(_data) _data
+#define BCMATTACHFN(_fn) _fn
+#define BCMPREATTACHDATA(_data) _data
+#define BCMPREATTACHFN(_fn) _fn
+#define BCMINITDATA(_data) _data
+#define BCMINITFN(_fn) _fn
+#define BCMUNINITFN(_fn) _fn
+#define BCMNMIATTACHFN(_fn) _fn
+#define BCMNMIATTACHDATA(_data) _data
+#define CONST const
+#if defined(BCM47XX) && defined(__ARM_ARCH_7A__)
+#define BCM47XX_CA9
+#else
+#undef BCM47XX_CA9
+#endif
+#if defined(BCM47XX_CA9)
+#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath")))
+#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host")))
+#else
+#define BCMFASTPATH
+#define BCMFASTPATH_HOST
+#endif
+
+#define BCMROMDATA(_data) _data
+#define BCMROMDAT_NAME(_data) _data
+#define BCMROMFN(_fn) _fn
+#define BCMROMFN_NAME(_fn) _fn
+#define STATIC static
+#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data)
+#define BCMROMDAT_SIZEOF(data) sizeof(data)
+#define BCMROMDAT_APATCH(data)
+#define BCMROMDAT_SPATCH(data)
+
+#define SI_BUS 0
+#define PCI_BUS 1
+#define PCMCIA_BUS 2
+#define SDIO_BUS 3
+#define JTAG_BUS 4
+#define USB_BUS 5
+#define SPI_BUS 6
+#define RPC_BUS 7
+
+#define BUSTYPE(bus) (bus)
+
+#define CHIPTYPE(bus) (bus)
+
+#define SPROMBUS (PCI_BUS)
+
+#define CHIPID(chip) (chip)
+
+#define CHIPREV(rev) (rev)
+
+#define DMADDR_MASK_32 0x0
+#define DMADDR_MASK_30 0xc0000000
+#define DMADDR_MASK_0 0xffffffff
+
+#define DMADDRWIDTH_30 30
+#define DMADDRWIDTH_32 32
+#define DMADDRWIDTH_63 63
+#define DMADDRWIDTH_64 64
+
+typedef unsigned long dmaaddr_t;
+#define PHYSADDRHI(_pa) (0)
+#define PHYSADDRHISET(_pa, _val)
+#define PHYSADDRLO(_pa) ((_pa))
+#define PHYSADDRLOSET(_pa, _val) \
+ do { \
+ (_pa) = (_val); \
+ } while (0)
+
+typedef struct {
+ dmaaddr_t addr;
+ uint32 length;
+} hnddma_seg_t;
+
+#define MAX_DMA_SEGS 8
+
+typedef struct {
+ void *oshdmah;
+ uint origsize;
+ uint nsegs;
+ hnddma_seg_t segs[MAX_DMA_SEGS];
+} hnddma_seg_map_t;
+
+#define BCMEXTRAHDROOM 204
+
+#define SDALIGN 32
+
+#define BCMDONGLEHDRSZ 12
+#define BCMDONGLEPADSZ 16
+
+#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
+
+#ifdef BCMDBG
+
+#ifndef BCMDBG_ERR
+#define BCMDBG_ERR
+#endif
+
+#ifndef BCMDBG_ASSERT
+#define BCMDBG_ASSERT
+#endif
+
+#endif
+
+#if defined(BCMDBG_ASSERT)
+#define BCMASSERT_SUPPORT
+#endif
+
+#define BITFIELD_MASK(width) \
+ (((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+ (((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+ (((val) & (~(field ## _M << field ## _S))) | \
+ ((unsigned)(bits) << field ## _S))
+
+#undef BCMSPACE
+#define bcmspace FALSE
+
+#ifndef MAXSZ_NVRAM_VARS
+#define MAXSZ_NVRAM_VARS 4096
+#endif
+
+#endif
diff --git a/src/include/bcmendian.h b/src/include/bcmendian.h
new file mode 100644
index 0000000..4b04c6e
--- /dev/null
+++ b/src/include/bcmendian.h
@@ -0,0 +1,280 @@
+/*
+ * Byte order utilities
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmendian.h 370210 2012-11-21 05:35:27Z $
+ *
+ * This file by default provides proper behavior on little-endian architectures.
+ * On big-endian architectures, IL_BIGENDIAN should be defined.
+ */
+
+#ifndef _BCMENDIAN_H_
+#define _BCMENDIAN_H_
+
+#include <typedefs.h>
+
+#define BCMSWAP16(val) \
+ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
+ (((uint16)(val) & (uint16)0xff00U) >> 8)))
+
+#define BCMSWAP32(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
+ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \
+ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \
+ (((uint32)(val) & (uint32)0xff000000U) >> 24)))
+
+#define BCMSWAP32BY16(val) \
+ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
+ (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
+
+#define BCMSWAP64(val) \
+ ((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
+ (((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64)(val) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64)(val) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64)(val) & 0xff00000000000000ULL) >> 56)))
+
+#define BCMSWAP64BY32(val) \
+ ((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
+ (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
+
+#ifndef hton16
+#define HTON16(i) BCMSWAP16(i)
+#define hton16(i) bcmswap16(i)
+#define HTON32(i) BCMSWAP32(i)
+#define hton32(i) bcmswap32(i)
+#define NTOH16(i) BCMSWAP16(i)
+#define ntoh16(i) bcmswap16(i)
+#define NTOH32(i) BCMSWAP32(i)
+#define ntoh32(i) bcmswap32(i)
+#define LTOH16(i) (i)
+#define ltoh16(i) (i)
+#define LTOH32(i) (i)
+#define ltoh32(i) (i)
+#define HTOL16(i) (i)
+#define htol16(i) (i)
+#define HTOL32(i) (i)
+#define htol32(i) (i)
+#define HTOL64(i) (i)
+#define htol64(i) (i)
+#endif
+
+#define ltoh16_buf(buf, i)
+#define htol16_buf(buf, i)
+
+#define load32_ua(a) ltoh32_ua(a)
+#define store32_ua(a, v) htol32_ua_store(v, a)
+#define load16_ua(a) ltoh16_ua(a)
+#define store16_ua(a, v) htol16_ua_store(v, a)
+
+#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8))
+#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
+#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1])
+#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
+
+#define ltoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#define ntoh_ua(ptr) \
+ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
+ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
+ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
+ *(uint8 *)0)
+
+#ifdef __GNUC__
+
+#define bcmswap16(val) ({ \
+ uint16 _val = (val); \
+ BCMSWAP16(_val); \
+})
+
+#define bcmswap32(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32(_val); \
+})
+
+#define bcmswap64(val) ({ \
+ uint64 _val = (val); \
+ BCMSWAP64(_val); \
+})
+
+#define bcmswap32by16(val) ({ \
+ uint32 _val = (val); \
+ BCMSWAP32BY16(_val); \
+})
+
+#define bcmswap16_buf(buf, len) ({ \
+ uint16 *_buf = (uint16 *)(buf); \
+ uint _wds = (len) / 2; \
+ while (_wds--) { \
+ *_buf = bcmswap16(*_buf); \
+ _buf++; \
+ } \
+})
+
+#define htol16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = _val >> 8; \
+})
+
+#define htol32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val & 0xff; \
+ _bytes[1] = (_val >> 8) & 0xff; \
+ _bytes[2] = (_val >> 16) & 0xff; \
+ _bytes[3] = _val >> 24; \
+})
+
+#define hton16_ua_store(val, bytes) ({ \
+ uint16 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 8; \
+ _bytes[1] = _val & 0xff; \
+})
+
+#define hton32_ua_store(val, bytes) ({ \
+ uint32 _val = (val); \
+ uint8 *_bytes = (uint8 *)(bytes); \
+ _bytes[0] = _val >> 24; \
+ _bytes[1] = (_val >> 16) & 0xff; \
+ _bytes[2] = (_val >> 8) & 0xff; \
+ _bytes[3] = _val & 0xff; \
+})
+
+#define ltoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH16_UA(_bytes); \
+})
+
+#define ltoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _LTOH32_UA(_bytes); \
+})
+
+#define ntoh16_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH16_UA(_bytes); \
+})
+
+#define ntoh32_ua(bytes) ({ \
+ const uint8 *_bytes = (const uint8 *)(bytes); \
+ _NTOH32_UA(_bytes); \
+})
+
+#else
+
+static INLINE uint16
+bcmswap16(uint16 val)
+{
+ return BCMSWAP16(val);
+}
+
+static INLINE uint32
+bcmswap32(uint32 val)
+{
+ return BCMSWAP32(val);
+}
+
+static INLINE uint64
+bcmswap64(uint64 val)
+{
+ return BCMSWAP64(val);
+}
+
+static INLINE uint32
+bcmswap32by16(uint32 val)
+{
+ return BCMSWAP32BY16(val);
+}
+
+static INLINE void
+bcmswap16_buf(uint16 *buf, uint len)
+{
+ len = len / 2;
+
+ while (len--) {
+ *buf = bcmswap16(*buf);
+ buf++;
+ }
+}
+
+static INLINE void
+htol16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = val >> 8;
+}
+
+static INLINE void
+htol32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val & 0xff;
+ bytes[1] = (val >> 8) & 0xff;
+ bytes[2] = (val >> 16) & 0xff;
+ bytes[3] = val >> 24;
+}
+
+static INLINE void
+hton16_ua_store(uint16 val, uint8 *bytes)
+{
+ bytes[0] = val >> 8;
+ bytes[1] = val & 0xff;
+}
+
+static INLINE void
+hton32_ua_store(uint32 val, uint8 *bytes)
+{
+ bytes[0] = val >> 24;
+ bytes[1] = (val >> 16) & 0xff;
+ bytes[2] = (val >> 8) & 0xff;
+ bytes[3] = val & 0xff;
+}
+
+static INLINE uint16
+ltoh16_ua(const void *bytes)
+{
+ return _LTOH16_UA((const uint8 *)bytes);
+}
+
+static INLINE uint32
+ltoh32_ua(const void *bytes)
+{
+ return _LTOH32_UA((const uint8 *)bytes);
+}
+
+static INLINE uint16
+ntoh16_ua(const void *bytes)
+{
+ return _NTOH16_UA((const uint8 *)bytes);
+}
+
+static INLINE uint32
+ntoh32_ua(const void *bytes)
+{
+ return _NTOH32_UA((const uint8 *)bytes);
+}
+
+#endif
+#endif
diff --git a/src/include/bcmutils.h b/src/include/bcmutils.h
new file mode 100644
index 0000000..5fafe3d
--- /dev/null
+++ b/src/include/bcmutils.h
@@ -0,0 +1,657 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: bcmutils.h 410746 2013-07-02 23:56:47Z $
+ */
+
+#ifndef _bcmutils_h_
+#define _bcmutils_h_
+
+#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src))
+#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count))
+#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src))
+#define bcm_sprintf_s snprintf
+
+#define _BCM_U 0x01
+#define _BCM_L 0x02
+#define _BCM_D 0x04
+#define _BCM_C 0x08
+#define _BCM_P 0x10
+#define _BCM_S 0x20
+#define _BCM_X 0x40
+#define _BCM_SP 0x80
+
+extern const unsigned char bcm_ctype[];
+#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)])
+
+#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0)
+#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0)
+#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0)
+#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0)
+#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0)
+#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0)
+#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0)
+#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0)
+#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0)
+#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0)
+#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c))
+
+struct bcmstrbuf {
+ char *buf;
+ unsigned int size;
+ char *origbuf;
+ unsigned int origsize;
+};
+
+#include <osl.h>
+
+#define GPIO_PIN_NOTDEFINED 0x20
+
+#define SPINWAIT_POLL_PERIOD 10
+
+#define SPINWAIT(exp, us) { \
+ uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \
+ while ((exp) && (countdown >= SPINWAIT_POLL_PERIOD)) {\
+ OSL_DELAY(SPINWAIT_POLL_PERIOD); \
+ countdown -= SPINWAIT_POLL_PERIOD; \
+ } \
+}
+
+#ifndef PKTQ_LEN_DEFAULT
+#define PKTQ_LEN_DEFAULT 128
+#endif
+#ifndef PKTQ_MAX_PREC
+#define PKTQ_MAX_PREC 16
+#endif
+
+typedef struct pktq_prec {
+ void *head;
+ void *tail;
+ uint16 len;
+ uint16 max;
+} pktq_prec_t;
+
+#define PKTQ_COMMON \
+ uint16 num_prec; \
+ uint16 hi_prec; \
+ uint16 max; \
+ uint16 len;
+
+struct pktq {
+ PKTQ_COMMON
+
+ struct pktq_prec q[PKTQ_MAX_PREC];
+};
+
+struct spktq {
+ PKTQ_COMMON
+
+ struct pktq_prec q[1];
+};
+
+#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
+
+typedef bool (*ifpkt_cb_t)(void*, int);
+
+#define POOL_ENAB(bus) 0
+#define SHARED_POOL ((struct pktpool *)NULL)
+
+#ifndef PKTPOOL_LEN_MAX
+#define PKTPOOL_LEN_MAX 40
+#endif
+#define PKTPOOL_CB_MAX 3
+
+struct pktpool;
+typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg);
+typedef struct {
+ pktpool_cb_t cb;
+ void *arg;
+} pktpool_cbinfo_t;
+
+typedef struct pktpool {
+ bool inited;
+ uint16 r;
+ uint16 w;
+ uint16 len;
+ uint16 maxlen;
+ uint16 plen;
+ bool istx;
+ bool empty;
+ uint8 cbtoggle;
+ uint8 cbcnt;
+ uint8 ecbcnt;
+ bool emptycb_disable;
+ pktpool_cbinfo_t *availcb_excl;
+ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX];
+ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX];
+ void *q[PKTPOOL_LEN_MAX + 1];
+
+} pktpool_t;
+
+#if defined(BCM4329C0)
+extern pktpool_t *pktpool_shared_ptr;
+#else
+extern pktpool_t *pktpool_shared;
+#endif
+
+extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx);
+extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal);
+extern void* pktpool_get(pktpool_t *pktp);
+extern void pktpool_free(pktpool_t *pktp, void *p);
+extern int pktpool_add(pktpool_t *pktp, void *p);
+extern uint16 pktpool_avail(pktpool_t *pktp);
+extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp);
+extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb);
+extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg);
+extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen);
+extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen);
+extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable);
+extern bool pktpool_emptycb_disabled(pktpool_t *pktp);
+
+#define POOLPTR(pp) ((pktpool_t *)(pp))
+#define pktpool_len(pp) (POOLPTR(pp)->len - 1)
+#define pktpool_plen(pp) (POOLPTR(pp)->plen)
+#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen)
+
+struct ether_addr;
+
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
+#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
+#define pktq_pmax(pq, prec) ((pq)->q[prec].max)
+#define pktq_plen(pq, prec) ((pq)->q[prec].len)
+#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len)
+#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max)
+#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0)
+
+#define pktq_ppeek(pq, prec) ((pq)->q[prec].head)
+#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail)
+
+extern void *pktq_penq(struct pktq *pq, int prec, void *p);
+extern void *pktq_penq_head(struct pktq *pq, int prec, void *p);
+extern void *pktq_pdeq(struct pktq *pq, int prec);
+extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p);
+extern void *pktq_pdeq_tail(struct pktq *pq, int prec);
+
+extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir,
+ ifpkt_cb_t fn, int arg);
+
+extern bool pktq_pdel(struct pktq *pq, void *p, int prec);
+
+extern int pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
+extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out);
+
+#define pktq_len(pq) ((int)(pq)->len)
+#define pktq_max(pq) ((int)(pq)->max)
+#define pktq_avail(pq) ((int)((pq)->max - (pq)->len))
+#define pktq_full(pq) ((pq)->len >= (pq)->max)
+#define pktq_empty(pq) ((pq)->len == 0)
+
+#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p))
+#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p))
+#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0)
+#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0)
+#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len)
+
+extern void pktq_init(struct pktq *pq, int num_prec, int max_len);
+extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len);
+
+extern void *pktq_deq(struct pktq *pq, int *prec_out);
+extern void *pktq_deq_tail(struct pktq *pq, int *prec_out);
+extern void *pktq_peek(struct pktq *pq, int *prec_out);
+extern void *pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg);
+
+extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf);
+extern uint pkttotlen(osl_t *osh, void *p);
+extern void *pktlast(osl_t *osh, void *p);
+extern uint pktsegcnt(osl_t *osh, void *p);
+extern uint pktsegcnt_war(osl_t *osh, void *p);
+extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset);
+extern void *pktoffset(osl_t *osh, void *p, uint offset);
+
+#define PKTPRIO_VDSCP 0x100
+#define PKTPRIO_VLAN 0x200
+#define PKTPRIO_UPD 0x400
+#define PKTPRIO_DSCP 0x800
+
+extern uint pktsetprio(void *pkt, bool update_vtag);
+
+extern int BCMROMFN(bcm_atoi)(const char *s);
+extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base);
+extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle);
+extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src);
+extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size);
+extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen);
+char* bcmstrtok(char **string, const char *delimiters, char *tokdelim);
+int bcmstricmp(const char *s1, const char *s2);
+int bcmstrnicmp(const char* s1, const char* s2, int cnt);
+
+extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
+extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea);
+
+struct ipv4_addr;
+extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
+extern char *bcm_ipv6_ntoa(void *ipv6, char *buf);
+
+extern void bcm_mdelay(uint ms);
+
+#define NVRAM_RECLAIM_CHECK(name)
+
+extern char *getvar(char *vars, const char *name);
+extern int getintvar(char *vars, const char *name);
+extern int getintvararray(char *vars, const char *name, int index);
+extern int getintvararraysize(char *vars, const char *name);
+extern uint getgpiopin(char *vars, char *pin_name, uint def_pin);
+#ifdef BCMDBG
+extern void prpkt(const char *msg, osl_t *osh, void *p0);
+#endif
+#define bcm_perf_enable()
+#define bcmstats(fmt)
+#define bcmlog(fmt, a1, a2)
+#define bcmdumplog(buf, size) *buf = '\0'
+#define bcmdumplogent(buf, idx) -1
+
+#define TSF_TICKS_PER_MS 1024
+#define bcmtslog(tstamp, fmt, a1, a2)
+#define bcmprinttslogs()
+#define bcmprinttstamp(us)
+#define bcmdumptslog(buf, size)
+
+extern char *bcm_nvram_vars(uint *length);
+extern int bcm_nvram_cache(void *sih);
+
+typedef struct bcm_iovar {
+ const char *name;
+ uint16 varid;
+ uint16 flags;
+ uint16 type;
+ uint16 minlen;
+} bcm_iovar_t;
+
+#define IOV_GET 0
+#define IOV_SET 1
+
+#define IOV_GVAL(id) ((id) * 2)
+#define IOV_SVAL(id) ((id) * 2 + IOV_SET)
+#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET)
+#define IOV_ID(actionid) (actionid >> 1)
+
+extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name);
+extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set);
+#if defined(BCMDBG)
+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
+#endif
+
+#define IOVT_VOID 0
+#define IOVT_BOOL 1
+#define IOVT_INT8 2
+#define IOVT_UINT8 3
+#define IOVT_INT16 4
+#define IOVT_UINT16 5
+#define IOVT_INT32 6
+#define IOVT_UINT32 7
+#define IOVT_BUFFER 8
+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
+
+#define BCM_IOV_TYPE_INIT { \
+ "void", \
+ "bool", \
+ "int8", \
+ "uint8", \
+ "int16", \
+ "uint16", \
+ "int32", \
+ "uint32", \
+ "buffer", \
+ "" }
+
+#define BCM_IOVT_IS_INT(type) (\
+ (type == IOVT_BOOL) || \
+ (type == IOVT_INT8) || \
+ (type == IOVT_UINT8) || \
+ (type == IOVT_INT16) || \
+ (type == IOVT_UINT16) || \
+ (type == IOVT_INT32) || \
+ (type == IOVT_UINT32))
+
+#define BCME_STRLEN 64
+#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST))
+
+#define BCME_OK 0
+#define BCME_ERROR -1
+#define BCME_BADARG -2
+#define BCME_BADOPTION -3
+#define BCME_NOTUP -4
+#define BCME_NOTDOWN -5
+#define BCME_NOTAP -6
+#define BCME_NOTSTA -7
+#define BCME_BADKEYIDX -8
+#define BCME_RADIOOFF -9
+#define BCME_NOTBANDLOCKED -10
+#define BCME_NOCLK -11
+#define BCME_BADRATESET -12
+#define BCME_BADBAND -13
+#define BCME_BUFTOOSHORT -14
+#define BCME_BUFTOOLONG -15
+#define BCME_BUSY -16
+#define BCME_NOTASSOCIATED -17
+#define BCME_BADSSIDLEN -18
+#define BCME_OUTOFRANGECHAN -19
+#define BCME_BADCHAN -20
+#define BCME_BADADDR -21
+#define BCME_NORESOURCE -22
+#define BCME_UNSUPPORTED -23
+#define BCME_BADLEN -24
+#define BCME_NOTREADY -25
+#define BCME_EPERM -26
+#define BCME_NOMEM -27
+#define BCME_ASSOCIATED -28
+#define BCME_RANGE -29
+#define BCME_NOTFOUND -30
+#define BCME_WME_NOT_ENABLED -31
+#define BCME_TSPEC_NOTFOUND -32
+#define BCME_ACM_NOTSUPPORTED -33
+#define BCME_NOT_WME_ASSOCIATION -34
+#define BCME_SDIO_ERROR -35
+#define BCME_DONGLE_DOWN -36
+#define BCME_VERSION -37
+#define BCME_TXFAIL -38
+#define BCME_RXFAIL -39
+#define BCME_NODEVICE -40
+#define BCME_NMODE_DISABLED -41
+#define BCME_NONRESIDENT -42
+#define BCME_SCANREJECT -43
+#define BCME_LAST BCME_SCANREJECT
+
+#define BCMERRSTRINGTABLE { \
+ "OK", \
+ "Undefined error", \
+ "Bad Argument", \
+ "Bad Option", \
+ "Not up", \
+ "Not down", \
+ "Not AP", \
+ "Not STA", \
+ "Bad Key Index", \
+ "Radio Off", \
+ "Not band locked", \
+ "No clock", \
+ "Bad Rate valueset", \
+ "Bad Band", \
+ "Buffer too short", \
+ "Buffer too long", \
+ "Busy", \
+ "Not Associated", \
+ "Bad SSID len", \
+ "Out of Range Channel", \
+ "Bad Channel", \
+ "Bad Address", \
+ "Not Enough Resources", \
+ "Unsupported", \
+ "Bad length", \
+ "Not Ready", \
+ "Not Permitted", \
+ "No Memory", \
+ "Associated", \
+ "Not In Range", \
+ "Not Found", \
+ "WME Not Enabled", \
+ "TSPEC Not Found", \
+ "ACM Not Supported", \
+ "Not WME Association", \
+ "SDIO Bus Error", \
+ "Dongle Not Accessible", \
+ "Incorrect version", \
+ "TX Failure", \
+ "RX Failure", \
+ "Device Not Present", \
+ "NMODE Disabled", \
+ "Nonresident overlay access", \
+ "Scan Rejected", \
+}
+
+#ifndef ABS
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef LIMIT_TO_RANGE
+#define LIMIT_TO_RANGE(x, min, max) \
+ ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+#endif
+
+#ifndef LIMIT_TO_MAX
+#define LIMIT_TO_MAX(x, max) \
+ (((x) > (max) ? (max) : (x)))
+#endif
+
+#ifndef LIMIT_TO_MIN
+#define LIMIT_TO_MIN(x, min) \
+ (((x) < (min) ? (min) : (x)))
+#endif
+
+#define CEIL(x, y) (((x) + ((y) - 1)) / (y))
+#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0)
+#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \
+ & ~((boundary) - 1))
+#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0)
+#define VALID_MASK(mask) !((mask) & ((mask) + 1))
+
+#ifndef OFFSETOF
+#ifdef __ARMCC_VERSION
+
+#include <stddef.h>
+#define OFFSETOF(type, member) offsetof(type, member)
+#elif __GNUC__ >= 4
+
+#define OFFSETOF(type, member) __builtin_offsetof(type, member)
+#else
+#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member)
+#endif
+#endif
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+extern void *_bcmutils_dummy_fn;
+#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f))
+
+#ifndef setbit
+#ifndef NBBY
+#define NBBY 8
+#endif
+#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY))
+#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY)))
+#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY)))
+#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0)
+#endif
+
+#define isbitset(a, i) (((a) & (1 << (i))) != 0)
+
+#define NBITS(type) (sizeof(type) * 8)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8)
+
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+#define MODADD(x, y, bound) \
+ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
+#define MODSUB(x, y, bound) \
+ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
+
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+#define CRC8_INIT_VALUE 0xff
+#define CRC8_GOOD_VALUE 0x9f
+#define CRC16_INIT_VALUE 0xffff
+#define CRC16_GOOD_VALUE 0xf0b8
+#define CRC32_INIT_VALUE 0xffffffff
+#define CRC32_GOOD_VALUE 0xdebb20e3
+
+#define MACF "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \
+ ((struct ether_addr *) (ea))->octet[1], \
+ ((struct ether_addr *) (ea))->octet[2], \
+ ((struct ether_addr *) (ea))->octet[3], \
+ ((struct ether_addr *) (ea))->octet[4], \
+ ((struct ether_addr *) (ea))->octet[5]
+
+#define ETHER_TO_MACF(ea) (ea).octet[0], \
+ (ea).octet[1], \
+ (ea).octet[2], \
+ (ea).octet[3], \
+ (ea).octet[4], \
+ (ea).octet[5]
+
+typedef struct bcm_bit_desc {
+ uint32 bit;
+ const char* name;
+} bcm_bit_desc_t;
+
+typedef struct bcm_bit_desc_ex {
+ uint32 mask;
+ const bcm_bit_desc_t *bitfield;
+} bcm_bit_desc_ex_t;
+
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+
+#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
+
+#define ETHER_ADDR_STR_LEN 18
+
+static INLINE void
+xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst)
+{
+ if (
+#ifdef __i386__
+ 1 ||
+#endif
+ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) {
+
+ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0];
+ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1];
+ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2];
+ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3];
+ } else {
+
+ int k;
+ for (k = 0; k < 16; k++)
+ dst[k] = src1[k] ^ src2[k];
+ }
+}
+
+extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc);
+
+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(BCMDBG_DUMP)
+
+extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len);
+
+extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len);
+#endif
+
+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(BCMDBG_DUMP) || \
+ defined(WLMEDIA_PEAKRATE)
+extern int bcm_format_hex(char *str, const void *bytes, int len);
+#endif
+
+#ifdef BCMDBG
+extern void deadbeef(void *p, uint len);
+#endif
+extern const char *bcm_crypto_algo_name(uint algo);
+extern char *bcm_chipname(uint chipid, char *buf, uint len);
+extern char *bcm_brev_str(uint32 brev, char *buf);
+extern void printbig(char *buf);
+extern void prhex(const char *msg, uchar *buf, uint len);
+
+extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key);
+
+extern const char *bcmerrorstr(int bcmerror);
+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key);
+
+typedef uint32 mbool;
+#define mboolset(mb, bit) ((mb) |= (bit))
+#define mboolclr(mb, bit) ((mb) &= ~(bit))
+#define mboolisset(mb, bit) (((mb) & (bit)) != 0)
+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val)))
+
+struct fielddesc {
+ const char *nameandfmt;
+ uint32 offset;
+ uint32 len;
+};
+
+extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
+extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len);
+
+extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount);
+extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes);
+extern void bcm_print_bytes(const char *name, const uchar *cdata, int len);
+
+typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset);
+extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str,
+ char *buf, uint32 bufsize);
+extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength);
+
+extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
+
+extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm);
+extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw);
+extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
+
+unsigned int process_nvram_vars(char *varbuf, unsigned int len);
+
+extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
+
+extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+#endif
diff --git a/src/include/epivers.h b/src/include/epivers.h
new file mode 100644
index 0000000..df6f248
--- /dev/null
+++ b/src/include/epivers.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#define EPI_MAJOR_VERSION 6
+
+#define EPI_MINOR_VERSION 30
+
+#define EPI_RC_NUMBER 223
+
+#define EPI_INCREMENTAL_NUMBER 271
+
+#define EPI_BUILD_NUMBER 0
+
+#define EPI_VERSION 6, 30, 223, 271
+
+#define EPI_VERSION_NUM 0x061edf10
+
+#define EPI_VERSION_DEV 6.30.223
+
+#define EPI_VERSION_STR "6.30.223.271 (r587334)"
+
+#endif
diff --git a/src/include/linux_osl.h b/src/include/linux_osl.h
new file mode 100644
index 0000000..bae45bb
--- /dev/null
+++ b/src/include/linux_osl.h
@@ -0,0 +1,338 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linux_osl.h 383331 2013-02-06 10:27:24Z $
+ */
+
+#ifndef _linux_osl_h_
+#define _linux_osl_h_
+
+#include <typedefs.h>
+
+extern void * osl_os_open_image(char * filename);
+extern int osl_os_get_image_block(char * buf, int len, void * image);
+extern void osl_os_close_image(void * image);
+extern int osl_os_image_size(void *image);
+
+extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag);
+extern void osl_detach(osl_t *osh);
+
+extern uint32 g_assert_type;
+
+#if defined(BCMDBG_ASSERT)
+ #define ASSERT(exp) \
+ do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
+extern void osl_assert(const char *exp, const char *file, int line);
+#else
+ #ifdef __GNUC__
+ #define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+ #if GCC_VERSION > 30100
+ #define ASSERT(exp) do {} while (0)
+ #else
+
+ #define ASSERT(exp)
+ #endif
+ #endif
+#endif
+
+#define OSL_DELAY(usec) osl_delay(usec)
+extern void osl_delay(uint usec);
+
+#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_read_attr((osh), (offset), (buf), (size))
+#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \
+ osl_pcmcia_write_attr((osh), (offset), (buf), (size))
+extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size);
+extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size);
+
+#define OSL_PCI_READ_CONFIG(osh, offset, size) \
+ osl_pci_read_config((osh), (offset), (size))
+#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \
+ osl_pci_write_config((osh), (offset), (size), (val))
+extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size);
+extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val);
+
+#define OSL_PCI_BUS(osh) osl_pci_bus(osh)
+#define OSL_PCI_SLOT(osh) osl_pci_slot(osh)
+extern uint osl_pci_bus(osl_t *osh);
+extern uint osl_pci_slot(osl_t *osh);
+extern struct pci_dev *osl_pci_device(osl_t *osh);
+
+typedef struct {
+ bool pkttag;
+ bool mmbus;
+ pktfree_cb_fn_t tx_fn;
+ void *tx_ctx;
+ void *unused[3];
+} osl_pubinfo_t;
+
+#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \
+ do { \
+ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \
+ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \
+ } while (0)
+
+#define BUS_SWAP32(v) (v)
+
+#ifdef BCMDBG_MEM
+ #define MALLOC(osh, size) osl_debug_malloc((osh), (size), __LINE__, __FILE__)
+ #define MFREE(osh, addr, size) osl_debug_mfree((osh), (addr), (size), __LINE__, __FILE__)
+ #define MALLOCED(osh) osl_malloced((osh))
+ #define MALLOC_DUMP(osh, b) osl_debug_memdump((osh), (b))
+ extern void *osl_debug_malloc(osl_t *osh, uint size, int line, const char* file);
+ extern void osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, const char* file);
+ extern uint osl_malloced(osl_t *osh);
+ struct bcmstrbuf;
+ extern int osl_debug_memdump(osl_t *osh, struct bcmstrbuf *b);
+#else
+ #define MALLOC(osh, size) osl_malloc((osh), (size))
+ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size))
+ #define MALLOCED(osh) osl_malloced((osh))
+ extern void *osl_malloc(osl_t *osh, uint size);
+ extern void osl_mfree(osl_t *osh, void *addr, uint size);
+ extern uint osl_malloced(osl_t *osh);
+#endif
+
+#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC)
+#define NATIVE_MFREE(osh, addr, size) kfree(addr)
+
+#define MALLOC_FAILED(osh) osl_malloc_failed((osh))
+extern uint osl_malloc_failed(osl_t *osh);
+
+#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align()
+#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+#define DMA_ALLOC_CONSISTENT_FORCE32(osh, size, align, tot, pap, dmah) \
+ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
+#define DMA_FREE_CONSISTENT_FORCE32(osh, va, size, pa, dmah) \
+ osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
+
+extern uint osl_dma_consistent_align(void);
+extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap);
+extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa);
+
+#define DMA_TX 1
+#define DMA_RX 2
+
+#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \
+ osl_dma_unmap((osh), (pa), (size), (direction))
+extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p,
+ hnddma_seg_map_t *txp_dmah);
+extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
+
+#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0)
+
+ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op
+ #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op
+
+#define OSL_ERROR(bcmerror) osl_error(bcmerror)
+extern int osl_error(int bcmerror);
+
+#define PKTBUFSZ 2048
+
+#if defined(LINUX_PORT)
+ #define printf(fmt, args...) printk(fmt , ## args)
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+
+ #define bcopy(src, dst, len) memcpy((dst), (src), (len))
+ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
+ #define bzero(b, len) memset((b), '\0', (len))
+
+ extern int osl_printf(const char *format, ...);
+ extern int osl_sprintf(char *buf, const char *format, ...);
+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...);
+ extern int osl_vsprintf(char *buf, const char *format, va_list ap);
+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap);
+ extern int osl_strcmp(const char *s1, const char *s2);
+ extern int osl_strncmp(const char *s1, const char *s2, uint n);
+ extern int osl_strlen(const char *s);
+ extern char* osl_strcpy(char *d, const char *s);
+ extern char* osl_strncpy(char *d, const char *s, uint n);
+ extern char* osl_strchr(const char *s, int c);
+ extern char* osl_strrchr(const char *s, int c);
+ extern void *osl_memset(void *d, int c, size_t n);
+ extern void *osl_memcpy(void *d, const void *s, size_t n);
+ extern void *osl_memmove(void *d, const void *s, size_t n);
+ extern int osl_memcmp(const void *s1, const void *s2, size_t n);
+#else
+
+ #include <stdarg.h>
+ #include <stddef.h>
+ #undef printf
+ #undef sprintf
+ #undef snprintf
+ #undef vsprintf
+ #undef vsnprintf
+ #define printf(fmt, args...) osl_printf((fmt) , ## args)
+ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args)
+ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args)
+ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap))
+ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap))
+ extern int osl_printf(const char *format, ...);
+ extern int osl_sprintf(char *buf, const char *format, ...);
+ extern int osl_snprintf(char *buf, size_t n, const char *format, ...);
+ extern int osl_vsprintf(char *buf, const char *format, va_list ap);
+ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap);
+
+ #undef strcmp
+ #undef strncmp
+ #undef strlen
+ #undef strcpy
+ #undef strncpy
+ #undef strchr
+ #undef strrchr
+ #define strcmp(s1, s2) osl_strcmp((s1), (s2))
+ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n))
+ #define strlen(s) osl_strlen((s))
+ #define strcpy(d, s) osl_strcpy((d), (s))
+ #define strncpy(d, s, n) osl_strncpy((d), (s), (n))
+ #define strchr(s, c) osl_strchr((s), (c))
+ #define strrchr(s, c) osl_strrchr((s), (c))
+ extern int osl_strcmp(const char *s1, const char *s2);
+ extern int osl_strncmp(const char *s1, const char *s2, uint n);
+ extern int osl_strlen(const char *s);
+ extern char* osl_strcpy(char *d, const char *s);
+ extern char* osl_strncpy(char *d, const char *s, uint n);
+ extern char* osl_strchr(const char *s, int c);
+ extern char* osl_strrchr(const char *s, int c);
+
+ #undef memset
+ #undef memcpy
+ #undef memcmp
+ #define memset(d, c, n) osl_memset((d), (c), (n))
+ #define memcpy(d, s, n) osl_memcpy((d), (s), (n))
+ #define memmove(d, s, n) osl_memmove((d), (s), (n))
+ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n))
+ extern void *osl_memset(void *d, int c, size_t n);
+ extern void *osl_memcpy(void *d, const void *s, size_t n);
+ extern void *osl_memmove(void *d, const void *s, size_t n);
+ extern int osl_memcmp(const void *s1, const void *s2, size_t n);
+
+ #undef bcopy
+ #undef bcmp
+ #undef bzero
+ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len))
+ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len))
+ #define bzero(b, len) osl_memset((b), '\0', (len))
+#endif
+
+#define R_REG(osh, r) (\
+ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \
+ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \
+ osl_readl((volatile uint32*)(r)) \
+)
+#define W_REG(osh, r, v) do { \
+ switch (sizeof(*(r))) { \
+ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \
+ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \
+ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \
+ } \
+} while (0)
+
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+extern uint8 osl_readb(volatile uint8 *r);
+extern uint16 osl_readw(volatile uint16 *r);
+extern uint32 osl_readl(volatile uint32 *r);
+extern void osl_writeb(uint8 v, volatile uint8 *r);
+extern void osl_writew(uint16 v, volatile uint16 *r);
+extern void osl_writel(uint32 v, volatile uint32 *r);
+
+#define OSL_SYSUPTIME() osl_sysuptime()
+extern uint32 osl_sysuptime(void);
+
+#define OSL_UNCACHED(va) osl_uncached((va))
+extern void *osl_uncached(void *va);
+#define OSL_CACHED(va) osl_cached((va))
+extern void *osl_cached(void *va);
+
+#define OSL_PREF_RANGE_LD(va, sz)
+#define OSL_PREF_RANGE_ST(va, sz)
+
+#define OSL_GETCYCLES(x) ((x) = osl_getcycles())
+extern uint osl_getcycles(void);
+
+#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr))
+extern int osl_busprobe(uint32 *val, uint32 addr);
+
+#define REG_MAP(pa, size) osl_reg_map((pa), (size))
+#define REG_UNMAP(va) osl_reg_unmap((va))
+extern void *osl_reg_map(uint32 pa, uint size);
+extern void osl_reg_unmap(void *va);
+
+#define R_SM(r) *(r)
+#define W_SM(r, v) (*(r) = (v))
+#define BZERO_SM(r, len) bzero((r), (len))
+
+#define PKTGET(osh, len, send) osl_pktget((osh), (len))
+#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
+#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb))
+#define PKTLIST_DUMP(osh, buf)
+#define PKTDBG_TRACE(osh, pkt, bit)
+#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send))
+#define PKTDATA(osh, skb) osl_pktdata((osh), (skb))
+#define PKTLEN(osh, skb) osl_pktlen((osh), (skb))
+#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb))
+#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb))
+#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb))
+#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x))
+#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len))
+#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes))
+#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes))
+#define PKTTAG(skb) osl_pkttag((skb))
+#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt))
+#define PKTLINK(skb) osl_pktlink((skb))
+#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x))
+#define PKTPRIO(skb) osl_pktprio((skb))
+#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x))
+#define PKTSHARED(skb) osl_pktshared((skb))
+#define PKTSETPOOL(osh, skb, x, y) do {} while (0)
+#define PKTPOOL(osh, skb) FALSE
+
+extern void *osl_pktget(osl_t *osh, uint len);
+extern void *osl_pktdup(osl_t *osh, void *skb);
+extern void *osl_pkt_frmnative(osl_t *osh, void *skb);
+extern void osl_pktfree(osl_t *osh, void *skb, bool send);
+extern uchar *osl_pktdata(osl_t *osh, void *skb);
+extern uint osl_pktlen(osl_t *osh, void *skb);
+extern uint osl_pktheadroom(osl_t *osh, void *skb);
+extern uint osl_pkttailroom(osl_t *osh, void *skb);
+extern void *osl_pktnext(osl_t *osh, void *skb);
+extern void osl_pktsetnext(void *skb, void *x);
+extern void osl_pktsetlen(osl_t *osh, void *skb, uint len);
+extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes);
+extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes);
+extern void *osl_pkttag(void *skb);
+extern void *osl_pktlink(void *skb);
+extern void osl_pktsetlink(void *skb, void *x);
+extern uint osl_pktprio(void *skb);
+extern void osl_pktsetprio(void *skb, uint x);
+extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt);
+extern bool osl_pktshared(void *skb);
+
+#define PKTALLOCED(osh) osl_pktalloced(osh)
+extern uint osl_pktalloced(osl_t *osh);
+
+#define DMA_MAP(osh, va, size, direction, p, dmah) \
+ osl_dma_map((osh), (va), (size), (direction), (p), (dmah))
+
+#endif
diff --git a/src/include/linuxver.h b/src/include/linuxver.h
new file mode 100644
index 0000000..b05bc32
--- /dev/null
+++ b/src/include/linuxver.h
@@ -0,0 +1,594 @@
+/*
+ * Linux-specific abstractions to gain some independence from linux kernel versions.
+ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linuxver.h 372519 2012-12-04 01:21:16Z $
+ */
+
+#ifndef _linuxver_h_
+#define _linuxver_h_
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#include <linux/config.h>
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+#include <generated/autoconf.h>
+#else
+#include <linux/autoconf.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
+#include <linux/kconfig.h>
+#endif
+
+#include <linux/module.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
+
+#ifdef __UNDEF_NO_VERSION__
+#undef __NO_VERSION__
+#else
+#define __NO_VERSION__
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i")
+#define module_param_string(_name_, _string_, _size_, _perm_) \
+ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#undef IP_TOS
+#endif
+#include <asm/io.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41))
+#include <linux/workqueue.h>
+#else
+#include <linux/tqueue.h>
+#ifndef work_struct
+#define work_struct tq_struct
+#endif
+#ifndef INIT_WORK
+#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data))
+#endif
+#ifndef schedule_work
+#define schedule_work(_work) schedule_task((_work))
+#endif
+#ifndef flush_scheduled_work
+#define flush_scheduled_work() flush_scheduled_tasks()
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define DAEMONIZE(a) daemonize(a); \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM);
+#else
+#define RAISE_RX_SOFTIRQ() \
+ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
+#define DAEMONIZE(a) daemonize(); \
+ do { if (a) \
+ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \
+ } while (0);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func)
+#else
+#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work)
+#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \
+ (RHEL_MAJOR == 5))
+
+typedef void (*work_func_t)(void *work);
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+#else
+typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67)
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
+#include <linux/sched.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <net/lib80211.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#include <linux/ieee80211.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#include <net/ieee80211.h>
+#endif
+#endif
+
+#ifdef CUSTOMER_HW4
+#include <linux/kthread.h>
+#endif
+
+#ifndef __exit
+#define __exit
+#endif
+#ifndef __devexit
+#define __devexit
+#endif
+#ifndef __devinit
+#define __devinit __init
+#endif
+#ifndef __devinitdata
+#define __devinitdata
+#endif
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+
+#define pci_get_drvdata(dev) (dev)->sysdata
+#define pci_set_drvdata(dev, value) (dev)->sysdata = (value)
+
+struct pci_device_id {
+ unsigned int vendor, device;
+ unsigned int subvendor, subdevice;
+ unsigned int class, class_mask;
+ unsigned long driver_data;
+};
+
+struct pci_driver {
+ struct list_head node;
+ char *name;
+ const struct pci_device_id *id_table;
+ int (*probe)(struct pci_dev *dev,
+ const struct pci_device_id *id);
+ void (*remove)(struct pci_dev *dev);
+ void (*suspend)(struct pci_dev *dev);
+ void (*resume)(struct pci_dev *dev);
+};
+
+#define MODULE_DEVICE_TABLE(type, name)
+#define PCI_ANY_ID (~0)
+
+#define pci_module_init pci_register_driver
+extern int pci_register_driver(struct pci_driver *drv);
+extern void pci_unregister_driver(struct pci_driver *drv);
+
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
+#define pci_module_init pci_register_driver
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18))
+#define module_init(x) __initcall(x);
+#define module_exit(x) __exitcall(x);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
+#define WL_USE_NETDEV_OPS
+#else
+#undef WL_USE_NETDEV_OPS
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL)
+#define WL_CONFIG_RFKILL
+#else
+#undef WL_CONFIG_RFKILL
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48))
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13))
+#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)])
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44))
+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23))
+#define pci_enable_device(dev) do { } while (0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14))
+#define net_device device
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42))
+
+#ifndef PCI_DMA_TODEVICE
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#endif
+
+typedef u32 dma_addr_t;
+
+static inline int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC | GFP_DMA;
+
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43))
+
+#define dev_kfree_skb_any(a) dev_kfree_skb(a)
+#define netif_down(dev) do { (dev)->start = 0; } while (0)
+
+#ifndef _COMPAT_NETDEVICE_H
+
+#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
+#define netif_wake_queue(dev) \
+ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0)
+#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+}
+
+#define netif_queue_stopped(dev) (dev)->tbusy
+#define netif_running(dev) (dev)->start
+
+#endif
+
+#define netif_device_attach(dev) netif_start_queue(dev)
+#define netif_device_detach(dev) netif_stop_queue(dev)
+
+#define tasklet_struct tq_struct
+static inline void tasklet_schedule(struct tasklet_struct *tasklet)
+{
+ queue_task(tasklet, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static inline void tasklet_init(struct tasklet_struct *tasklet,
+ void (*func)(unsigned long),
+ unsigned long data)
+{
+ tasklet->next = NULL;
+ tasklet->sync = 0;
+ tasklet->routine = (void (*)(void *))func;
+ tasklet->data = (void *)data;
+}
+#define tasklet_kill(tasklet) { do {} while (0); }
+
+#define del_timer_sync(timer) del_timer(timer)
+
+#else
+
+#define netif_down(dev)
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3))
+
+#define PREPARE_TQUEUE(_tq, _routine, _data) \
+ do { \
+ (_tq)->routine = _routine; \
+ (_tq)->data = _data; \
+ } while (0)
+
+#define INIT_TQUEUE(_tq, _routine, _data) \
+ do { \
+ INIT_LIST_HEAD(&(_tq)->list); \
+ (_tq)->sync = 0; \
+ PREPARE_TQUEUE((_tq), (_routine), (_data)); \
+ } while (0)
+
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
+#define PCI_SAVE_STATE(a, b) pci_save_state(a)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a)
+#else
+#define PCI_SAVE_STATE(a, b) pci_save_state(a, b)
+#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6))
+static inline int
+pci_save_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(dev, i * 4, &buffer[i]);
+ }
+ return 0;
+}
+
+static inline int
+pci_restore_state(struct pci_dev *dev, u32 *buffer)
+{
+ int i;
+
+ if (buffer) {
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(dev, i * 4, buffer[i]);
+ }
+
+ else {
+ for (i = 0; i < 6; i ++)
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_0 + (i * 4),
+ pci_resource_start(dev, i));
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+ return 0;
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19))
+#define read_c0_count() read_32bit_cp0_register(CP0_COUNT)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#else
+#define OLD_MOD_INC_USE_COUNT do {} while (0)
+#define OLD_MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#else
+#ifndef SET_MODULE_OWNER
+#define SET_MODULE_OWNER(dev) do {} while (0)
+#endif
+#ifndef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT do {} while (0)
+#endif
+#ifndef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT do {} while (0)
+#endif
+#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#endif
+
+#ifndef SET_NETDEV_DEV
+#define SET_NETDEV_DEV(net, pdev) do {} while (0)
+#endif
+
+#ifndef HAVE_FREE_NETDEV
+#define free_netdev(dev) kfree(dev)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+
+#define af_packet_priv data
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+#define DRV_SUSPEND_STATE_TYPE pm_message_t
+#else
+#define DRV_SUSPEND_STATE_TYPE uint32
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define CHECKSUM_HW CHECKSUM_PARTIAL
+#endif
+
+typedef struct {
+ void *parent;
+ struct task_struct *p_task;
+ long thr_pid;
+ int prio;
+ struct semaphore sema;
+ int terminated;
+ struct completion completed;
+} tsk_ctl_t;
+
+#define DBG_THR(x)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x)
+#else
+#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x)
+#endif
+
+#define PROC_START(thread_func, owner, tsk_ctl, flags) \
+{ \
+ sema_init(&((tsk_ctl)->sema), 0); \
+ init_completion(&((tsk_ctl)->completed)); \
+ (tsk_ctl)->parent = owner; \
+ (tsk_ctl)->terminated = FALSE; \
+ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \
+ if ((tsk_ctl)->thr_pid > 0) \
+ wait_for_completion(&((tsk_ctl)->completed)); \
+ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+}
+
+#ifdef USE_KTHREAD_API
+#define PROC_START2(thread_func, owner, tsk_ctl, flags, name) \
+{ \
+ sema_init(&((tsk_ctl)->sema), 0); \
+ init_completion(&((tsk_ctl)->completed)); \
+ (tsk_ctl)->parent = owner; \
+ (tsk_ctl)->terminated = FALSE; \
+ (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \
+ (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \
+ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+}
+#endif
+
+#define PROC_STOP(tsk_ctl) \
+{ \
+ (tsk_ctl)->terminated = TRUE; \
+ smp_wmb(); \
+ up(&((tsk_ctl)->sema)); \
+ wait_for_completion(&((tsk_ctl)->completed)); \
+ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \
+ (tsk_ctl)->thr_pid = -1; \
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+#define KILL_PROC(nr, sig) \
+{ \
+struct task_struct *tsk; \
+struct pid *pid; \
+pid = find_get_pid((pid_t)nr); \
+tsk = pid_task(pid, PIDTYPE_PID); \
+if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 30))
+#define KILL_PROC(pid, sig) \
+{ \
+ struct task_struct *tsk; \
+ tsk = find_task_by_vpid(pid); \
+ if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#define KILL_PROC(pid, sig) \
+{ \
+ kill_proc(pid, sig, 1); \
+}
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#include <linux/time.h>
+#include <linux/wait.h>
+#else
+#include <linux/sched.h>
+
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ wait_queue_t __wait; \
+ init_waitqueue_entry(&__wait, current); \
+ \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret); \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ __ret; \
+})
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define DEV_PRIV(dev) (dev->priv)
+#else
+#define DEV_PRIV(dev) netdev_priv(dev)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+#define WL_ISR(i, d, p) wl_isr((i), (d))
+#else
+#define WL_ISR(i, d, p) wl_isr((i), (d), (p))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
+#define netdev_priv(dev) dev->priv
+#endif
+
+#endif
diff --git a/src/include/osl.h b/src/include/osl.h
new file mode 100644
index 0000000..407b257
--- /dev/null
+++ b/src/include/osl.h
@@ -0,0 +1,132 @@
+/*
+ * OS Abstraction Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: osl.h 431503 2013-10-23 21:42:47Z $
+ */
+
+#ifndef _osl_h_
+#define _osl_h_
+
+typedef struct osl_info osl_t;
+typedef struct osl_dmainfo osldma_t;
+
+#define OSL_PKTTAG_SZ 32
+
+typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status);
+
+typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size);
+typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size);
+
+#ifdef __mips__
+#define PREF_LOAD 0
+#define PREF_STORE 1
+#define PREF_LOAD_STREAMED 4
+#define PREF_STORE_STREAMED 5
+#define PREF_LOAD_RETAINED 6
+#define PREF_STORE_RETAINED 7
+#define PREF_WBACK_INV 25
+#define PREF_PREPARE4STORE 30
+
+#define MAKE_PREFETCH_FN(hint) \
+static inline void prefetch_##hint(const void *addr) \
+{ \
+ __asm__ __volatile__(\
+ " .set mips4 \n" \
+ " pref %0, (%1) \n" \
+ " .set mips0 \n" \
+ : \
+ : "i" (hint), "r" (addr)); \
+}
+
+#define MAKE_PREFETCH_RANGE_FN(hint) \
+static inline void prefetch_range_##hint(const void *addr, int len) \
+{ \
+ int size = len; \
+ while (size > 0) { \
+ prefetch_##hint(addr); \
+ size -= 32; \
+ } \
+}
+
+MAKE_PREFETCH_FN(PREF_LOAD)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD)
+MAKE_PREFETCH_FN(PREF_STORE)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE)
+MAKE_PREFETCH_FN(PREF_LOAD_STREAMED)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED)
+MAKE_PREFETCH_FN(PREF_STORE_STREAMED)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED)
+MAKE_PREFETCH_FN(PREF_LOAD_RETAINED)
+MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED)
+MAKE_PREFETCH_FN(PREF_STORE_RETAINED)
+MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED)
+#endif
+
+#include <linux_osl.h>
+
+#ifndef PKTDBG_TRACE
+#define PKTDBG_TRACE(osh, pkt, bit)
+#endif
+
+#define PKTCTFMAP(osh, p)
+
+#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
+
+#ifndef AND_REG
+#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v))
+#endif
+
+#ifndef OR_REG
+#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v))
+#endif
+
+#if !defined(OSL_SYSUPTIME)
+#define OSL_SYSUPTIME() (0)
+#define OSL_SYSUPTIME_SUPPORT FALSE
+#else
+#define OSL_SYSUPTIME_SUPPORT TRUE
+#endif
+
+#if !defined(PKTC_DONGLE)
+#define PKTCGETATTR(s) (0)
+#define PKTCSETATTR(skb, f, p, b)
+#define PKTCCLRATTR(skb)
+#define PKTCCNT(skb) (1)
+#define PKTCLEN(skb) PKTLEN(NULL, skb)
+#define PKTCGETFLAGS(skb) (0)
+#define PKTCSETFLAGS(skb, f)
+#define PKTCCLRFLAGS(skb)
+#define PKTCFLAGS(skb) (0)
+#define PKTCSETCNT(skb, c)
+#define PKTCINCRCNT(skb)
+#define PKTCADDCNT(skb, c)
+#define PKTCSETLEN(skb, l)
+#define PKTCADDLEN(skb, l)
+#define PKTCSETFLAG(skb, fb)
+#define PKTCCLRFLAG(skb, fb)
+#define PKTCLINK(skb) NULL
+#define PKTSETCLINK(skb, x)
+#define FOREACH_CHAINED_PKT(skb, nskb) \
+ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb))
+#define PKTCFREE PKTFREE
+#endif
+
+#define PKTSETCHAINED(osh, skb)
+#define PKTCLRCHAINED(osh, skb)
+#define PKTISCHAINED(skb) (FALSE)
+
+#endif
diff --git a/src/include/packed_section_end.h b/src/include/packed_section_end.h
new file mode 100644
index 0000000..8a98795
--- /dev/null
+++ b/src/include/packed_section_end.h
@@ -0,0 +1,41 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: packed_section_end.h 395414 2013-04-07 19:26:09Z $
+ */
+
+#ifdef BWL_PACKED_SECTION
+ #undef BWL_PACKED_SECTION
+#else
+ #error "BWL_PACKED_SECTION is NOT defined!"
+#endif
+
+#undef BWL_PRE_PACKED_STRUCT
+#undef BWL_POST_PACKED_STRUCT
diff --git a/src/include/packed_section_start.h b/src/include/packed_section_start.h
new file mode 100644
index 0000000..4922850
--- /dev/null
+++ b/src/include/packed_section_start.h
@@ -0,0 +1,48 @@
+/*
+ * Declare directives for structure packing. No padding will be provided
+ * between the members of packed structures, and therefore, there is no
+ * guarantee that structure members will be aligned.
+ *
+ * Declaring packed structures is compiler specific. In order to handle all
+ * cases, packed structures should be delared as:
+ *
+ * #include <packed_section_start.h>
+ *
+ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t {
+ * some_struct_members;
+ * } BWL_POST_PACKED_STRUCT foobar_t;
+ *
+ * #include <packed_section_end.h>
+ *
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: packed_section_start.h 395414 2013-04-07 19:26:09Z $
+ */
+
+#ifdef BWL_PACKED_SECTION
+ #error "BWL_PACKED_SECTION is already defined!"
+#else
+ #define BWL_PACKED_SECTION
+#endif
+
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_PRE_PACKED_STRUCT
+ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed))
+#elif defined(__CC_ARM)
+ #define BWL_PRE_PACKED_STRUCT __packed
+ #define BWL_POST_PACKED_STRUCT
+#else
+ #error "Unknown compiler!"
+#endif
diff --git a/src/include/pcicfg.h b/src/include/pcicfg.h
new file mode 100644
index 0000000..784b56f
--- /dev/null
+++ b/src/include/pcicfg.h
@@ -0,0 +1,83 @@
+/*
+ * pcicfg.h: PCI configuration constants and structures.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: pcicfg.h 392809 2013-03-24 22:49:08Z $
+ */
+
+#ifndef _h_pcicfg_
+#define _h_pcicfg_
+
+#define PCI_CFG_VID 0
+#define PCI_CFG_DID 2
+#define PCI_CFG_CMD 4
+#define PCI_CFG_STAT 6
+#define PCI_CFG_REV 8
+#define PCI_CFG_PROGIF 9
+#define PCI_CFG_SUBCL 0xa
+#define PCI_CFG_BASECL 0xb
+#define PCI_CFG_CLSZ 0xc
+#define PCI_CFG_LATTIM 0xd
+#define PCI_CFG_HDR 0xe
+#define PCI_CFG_BIST 0xf
+#define PCI_CFG_BAR0 0x10
+#define PCI_CFG_BAR1 0x14
+#define PCI_CFG_BAR2 0x18
+#define PCI_CFG_BAR3 0x1c
+#define PCI_CFG_BAR4 0x20
+#define PCI_CFG_BAR5 0x24
+#define PCI_CFG_CIS 0x28
+#define PCI_CFG_SVID 0x2c
+#define PCI_CFG_SSID 0x2e
+#define PCI_CFG_ROMBAR 0x30
+#define PCI_CFG_CAPPTR 0x34
+#define PCI_CFG_INT 0x3c
+#define PCI_CFG_PIN 0x3d
+#define PCI_CFG_MINGNT 0x3e
+#define PCI_CFG_MAXLAT 0x3f
+#define PCI_CFG_DEVCTRL 0xd8
+#define PCI_BAR0_WIN 0x80
+#define PCI_BAR1_WIN 0x84
+#define PCI_SPROM_CONTROL 0x88
+#define PCI_BAR1_CONTROL 0x8c
+#define PCI_INT_STATUS 0x90
+#define PCI_INT_MASK 0x94
+#define PCI_TO_SB_MB 0x98
+#define PCI_BACKPLANE_ADDR 0xa0
+#define PCI_BACKPLANE_DATA 0xa4
+#define PCI_CLK_CTL_ST 0xa8
+#define PCI_BAR0_WIN2 0xac
+#define PCI_GPIO_IN 0xb0
+#define PCI_GPIO_OUT 0xb4
+#define PCI_GPIO_OUTEN 0xb8
+
+#define PCI_BAR0_SHADOW_OFFSET (2 * 1024)
+#define PCI_BAR0_SPROM_OFFSET (4 * 1024)
+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024)
+#define PCI_BAR0_PCISBR_OFFSET (4 * 1024)
+
+#define PCIE2_BAR0_WIN2 0x70
+#define PCIE2_BAR0_CORE2_WIN 0x74
+#define PCIE2_BAR0_CORE2_WIN2 0x78
+
+#define PCI_BAR0_WINSZ (16 * 1024)
+
+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
+#define PCI_16KB0_CCREGS_OFFSET (12 * 1024)
+#define PCI_16KBB0_WINSZ (16 * 1024)
+
+#define PCI_CONFIG_SPACE_SIZE 256
+#endif
diff --git a/src/include/siutils.h b/src/include/siutils.h
new file mode 100644
index 0000000..fad8f62
--- /dev/null
+++ b/src/include/siutils.h
@@ -0,0 +1,409 @@
+/*
+ * Misc utility routines for accessing the SOC Interconnects
+ * of Broadcom HNBU chips.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: siutils.h 434387 2013-11-06 04:50:08Z $
+ */
+
+#ifndef _siutils_h_
+#define _siutils_h_
+
+#include <bcmutils.h>
+
+struct si_pub {
+ uint socitype;
+
+ uint bustype;
+ uint buscoretype;
+ uint buscorerev;
+ uint buscoreidx;
+ int ccrev;
+ uint32 cccaps;
+ uint32 cccaps_ext;
+ int pmurev;
+ uint32 pmucaps;
+ uint boardtype;
+ uint boardrev;
+ uint boardvendor;
+ uint boardflags;
+ uint boardflags2;
+ uint chip;
+ uint chiprev;
+ uint chippkg;
+ uint32 chipst;
+ bool issim;
+ uint socirev;
+ bool pci_pr32414;
+
+#ifdef SI_ENUM_BASE_VARIABLE
+ uint32 si_enum_base;
+#endif
+};
+
+typedef const struct si_pub si_t;
+
+#ifdef ATE_BUILD
+typedef struct _ate_params {
+ void* wl;
+ uint8 gpio_input;
+ uint8 gpio_output;
+ bool cmd_proceed;
+ uint16 cmd_idx;
+ bool ate_cmd_done;
+} ate_params_t;
+#endif
+
+#define SI_OSH NULL
+
+#define BADIDX (SI_MAXCORES + 1)
+
+#define XTAL 0x1
+#define PLL 0x2
+
+#define CLK_FAST 0
+#define CLK_DYNAMIC 2
+
+#define GPIO_DRV_PRIORITY 0
+#define GPIO_APP_PRIORITY 1
+#define GPIO_HI_PRIORITY 2
+
+#define GPIO_PULLUP 0
+#define GPIO_PULLDN 1
+
+#define GPIO_REGEVT 0
+#define GPIO_REGEVT_INTMSK 1
+#define GPIO_REGEVT_INTPOL 2
+
+#define SI_DEVPATH_BUFSZ 16
+
+#define SI_DOATTACH 1
+#define SI_PCIDOWN 2
+#define SI_PCIUP 3
+
+#define ISSIM_ENAB(sih) FALSE
+
+#if defined(BCMPMUCTL)
+#define PMUCTL_ENAB(sih) (BCMPMUCTL)
+#else
+#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU)
+#endif
+
+#if defined(BCMPMUCTL) && BCMPMUCTL
+#define CCCTL_ENAB(sih) (0)
+#define CCPLL_ENAB(sih) (0)
+#else
+#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL)
+#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK)
+#endif
+
+typedef void (*gpio_handler_t)(uint32 stat, void *arg);
+
+#define CC_BTCOEX_EN_MASK 0x01
+
+#define GPIO_CTRL_EPA_EN_MASK 0x40
+
+#define GPIO_CTRL_5_6_EN_MASK 0x60
+#define GPIO_CTRL_7_6_EN_MASK 0xC0
+#define GPIO_OUT_7_EN_MASK 0x80
+
+#define SI_CR4_CAP (0x04)
+#define SI_CR4_BANKIDX (0x40)
+#define SI_CR4_BANKINFO (0x44)
+
+#define ARMCR4_TCBBNB_MASK 0xf0
+#define ARMCR4_TCBBNB_SHIFT 4
+#define ARMCR4_TCBANB_MASK 0xf
+#define ARMCR4_TCBANB_SHIFT 0
+
+#define SICF_CPUHALT (0x0020)
+#define ARMCR4_BSZ_MASK 0x3f
+#define ARMCR4_BSZ_MULT 8192
+
+extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype,
+ void *sdh, char **vars, uint *varsz);
+extern si_t *si_kattach(osl_t *osh);
+extern void si_detach(si_t *sih);
+extern bool si_pci_war16165(si_t *sih);
+
+extern uint si_corelist(si_t *sih, uint coreid[]);
+extern uint si_coreid(si_t *sih);
+extern uint si_flag(si_t *sih);
+extern uint si_flag_alt(si_t *sih);
+extern uint si_intflag(si_t *sih);
+extern uint si_coreidx(si_t *sih);
+extern uint si_coreunit(si_t *sih);
+extern uint si_corevendor(si_t *sih);
+extern uint si_corerev(si_t *sih);
+extern void *si_osh(si_t *sih);
+extern void si_setosh(si_t *sih, osl_t *osh);
+extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
+extern void *si_coreregs(si_t *sih);
+extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val);
+extern void *si_wrapperregs(si_t *sih);
+extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val);
+extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val);
+extern bool si_iscoreup(si_t *sih);
+extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit);
+extern void *si_setcoreidx(si_t *sih, uint coreidx);
+extern void *si_setcore(si_t *sih, uint coreid, uint coreunit);
+extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val);
+extern void si_restore_core(si_t *sih, uint coreid, uint intr_val);
+extern int si_numaddrspaces(si_t *sih);
+extern uint32 si_addrspace(si_t *sih, uint asidx);
+extern uint32 si_addrspacesize(si_t *sih, uint asidx);
+extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size);
+extern int si_corebist(si_t *sih);
+extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
+extern void si_core_disable(si_t *sih, uint32 bits);
+extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m);
+extern uint si_chip_hostif(si_t *sih);
+extern bool si_read_pmu_autopll(si_t *sih);
+extern uint32 si_clock(si_t *sih);
+extern uint32 si_alp_clock(si_t *sih);
+extern uint32 si_ilp_clock(si_t *sih);
+extern void si_pci_setup(si_t *sih, uint coremask);
+extern void si_pcmcia_init(si_t *sih);
+extern void si_setint(si_t *sih, int siflag);
+extern bool si_backplane64(si_t *sih);
+extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
+ void *intrsenabled_fn, void *intr_arg);
+extern void si_deregister_intr_callback(si_t *sih);
+extern void si_clkctl_init(si_t *sih);
+extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih);
+extern bool si_clkctl_cc(si_t *sih, uint mode);
+extern int si_clkctl_xtal(si_t *sih, uint what, bool on);
+extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val);
+extern void si_btcgpiowar(si_t *sih);
+extern bool si_deviceremoved(si_t *sih);
+extern uint32 si_socram_size(si_t *sih);
+extern uint32 si_socdevram_size(si_t *sih);
+extern void si_socdevram(si_t *sih, bool set, uint8 *ennable, uint8 *protect, uint8 *remap);
+extern bool si_socdevram_pkg(si_t *sih);
+extern bool si_socdevram_remap_isenb(si_t *sih);
+extern uint32 si_socdevram_remap_size(si_t *sih);
+
+extern void si_watchdog(si_t *sih, uint ticks);
+extern void si_watchdog_ms(si_t *sih, uint32 ms);
+extern uint32 si_watchdog_msticks(void);
+extern void *si_gpiosetcore(si_t *sih);
+extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioin(si_t *sih);
+extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority);
+extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority);
+extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val);
+extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val);
+extern uint32 si_gpio_int_enable(si_t *sih, bool enable);
+
+extern void *si_gpio_handler_register(si_t *sih, uint32 e, bool lev, gpio_handler_t cb, void *arg);
+extern void si_gpio_handler_unregister(si_t *sih, void* gpioh);
+extern void si_gpio_handler_process(si_t *sih);
+
+extern bool si_pci_pmecap(si_t *sih);
+struct osl_info;
+extern bool si_pci_fastpmecap(struct osl_info *osh);
+extern bool si_pci_pmestat(si_t *sih);
+extern void si_pci_pmeclr(si_t *sih);
+extern void si_pci_pmeen(si_t *sih);
+extern void si_pci_pmestatclr(si_t *sih);
+extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset);
+extern uint si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val);
+
+extern uint16 si_d11_devid(si_t *sih);
+extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
+ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader);
+
+#if defined(BCMECICOEX)
+extern bool si_eci(si_t *sih);
+extern int si_eci_init(si_t *sih);
+extern void si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt);
+extern bool si_seci(si_t *sih);
+extern void* si_seci_init(si_t *sih, uint8 seci_mode);
+extern void* si_gci_init(si_t *sih);
+extern void si_seci_down(si_t *sih);
+extern void si_seci_upd(si_t *sih, bool enable);
+extern bool si_gci(si_t *sih);
+#else
+#define si_eci(sih) 0
+static INLINE void * si_eci_init(si_t *sih) {return NULL;}
+#define si_eci_notify_bt(sih, type, val) (0)
+#define si_seci(sih) 0
+#define si_seci_upd(sih, a) do {} while (0)
+static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;}
+static INLINE void * si_gci_init(si_t *sih) {return NULL;}
+#define si_seci_down(sih) do {} while (0)
+#define si_gci(sih) 0
+#endif
+
+extern bool si_is_otp_disabled(si_t *sih);
+extern bool si_is_otp_powered(si_t *sih);
+extern void si_otp_power(si_t *sih, bool on);
+
+extern bool si_is_sprom_available(si_t *sih);
+extern bool si_is_sprom_enabled(si_t *sih);
+extern void si_sprom_enable(si_t *sih, bool enable);
+#ifdef SI_SPROM_PROBE
+extern void si_sprom_init(si_t *sih);
+#endif
+
+extern int si_cis_source(si_t *sih);
+#define CIS_DEFAULT 0
+#define CIS_SROM 1
+#define CIS_OTP 2
+
+#define DEFAULT_FAB 0x0
+#define CSM_FAB7 0x1
+#define TSMC_FAB12 0x2
+#define SMIC_FAB4 0x3
+
+extern int BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw);
+extern uint16 BCMATTACHFN(si_fabid)(si_t *sih);
+
+extern int si_devpath(si_t *sih, char *path, int size);
+
+extern char *si_getdevpathvar(si_t *sih, const char *name);
+extern int si_getdevpathintvar(si_t *sih, const char *name);
+extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name);
+
+extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val);
+extern uint8 si_pcieobffenable(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltr_reg(si_t *sih, uint32 reg, uint32 mask, uint32 val);
+extern uint32 si_pcieltrspacing_reg(si_t *sih, uint32 mask, uint32 val);
+extern uint32 si_pcieltrhysteresiscnt_reg(si_t *sih, uint32 mask, uint32 val);
+extern void si_pcie_set_error_injection(si_t *sih, uint32 mode);
+extern void si_pcie_set_L1substate(si_t *sih, uint32 substate);
+extern uint32 si_pcie_get_L1substate(si_t *sih);
+extern void si_war42780_clkreq(si_t *sih, bool clkreq);
+extern void si_pci_down(si_t *sih);
+extern void si_pci_up(si_t *sih);
+extern void si_pci_sleep(si_t *sih);
+extern void si_pcie_war_ovr_update(si_t *sih, uint8 aspm);
+extern void si_pcie_power_save_enable(si_t *sih, bool enable);
+extern void si_pcie_extendL1timer(si_t *sih, bool extend);
+extern int si_pci_fixcfg(si_t *sih);
+extern bool si_ldo_war(si_t *sih, uint devid);
+extern void si_chippkg_set(si_t *sih, uint);
+
+extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on);
+extern void si_chipcontrl_restore(si_t *sih, uint32 val);
+extern uint32 si_chipcontrl_read(si_t *sih);
+extern void si_chipcontrl_epa4331(si_t *sih, bool on);
+extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl);
+extern void si_chipcontrl_srom4360(si_t *sih, bool on);
+
+extern void si_epa_4313war(si_t *sih);
+extern void si_btc_enable_chipcontrol(si_t *sih);
+
+extern void si_btcombo_p250_4313_war(si_t *sih);
+extern void si_btcombo_43228_war(si_t *sih);
+extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear);
+extern void si_pmu_synth_pwrsw_4313_war(si_t *sih);
+extern uint si_pll_reset(si_t *sih);
+
+extern bool si_taclear(si_t *sih, bool details);
+
+#ifdef BCMDBG
+extern void si_view(si_t *sih, bool verbose);
+extern void si_viewall(si_t *sih, bool verbose);
+#if defined(BCM_BACKPLANE_TIMEOUT)
+extern void si_setup_backplanetimeout(osl_t *osh, si_t *sih, uint val);
+extern void si_setup_curmap(osl_t *osh, si_t *sih);
+#endif
+#endif
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+extern int si_dump_pcieinfo(si_t *sih, struct bcmstrbuf *b);
+#endif
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+struct bcmstrbuf;
+extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b);
+#endif
+extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type);
+extern uint32 write_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val);
+extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val);
+extern void si_pcie_set_request_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_request_size(si_t *sih);
+extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size);
+extern uint16 si_pcie_get_maxpayload_size(si_t *sih);
+extern uint16 si_pcie_get_ssid(si_t *sih);
+extern uint32 si_pcie_get_bar0(si_t *sih);
+extern int si_pcie_configspace_cache(si_t *sih);
+extern int si_pcie_configspace_restore(si_t *sih);
+extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size);
+
+char *si_getnvramflvar(si_t *sih, const char *name);
+
+extern void BCMATTACHFN(si_muxenab)(si_t *sih, uint32 w);
+
+extern uint32 si_tcm_size(si_t *sih);
+extern bool si_has_flops(si_t *sih);
+
+extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_indirect(si_t *sih, uint regidx, uint offset, uint32 mask, uint32 val);
+extern uint32 si_gci_output(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern uint32 si_gci_input(si_t *sih, uint reg);
+extern uint32 si_gci_int_enable(si_t *sih, bool enable);
+extern void si_gci_reset(si_t *sih);
+extern void si_ercx_init(si_t *sih);
+extern void si_wci2_init(si_t *sih);
+extern void si_gci_seci_init(si_t *sih);
+extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel);
+extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos);
+extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val);
+extern int si_set_sromctl(si_t *sih, uint32 value);
+extern uint32 si_get_sromctl(si_t *sih);
+
+extern uint16 si_cc_get_reg16(uint32 reg_offs);
+extern uint32 si_cc_get_reg32(uint32 reg_offs);
+extern uint32 si_cc_set_reg32(uint32 reg_offs, uint32 val);
+extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 mask);
+
+#define CHIPCTRLREG1 0x1
+#define CHIPCTRLREG2 0x2
+#define CHIPCTRLREG3 0x3
+#define CHIPCTRLREG4 0x4
+#define CHIPCTRLREG5 0x5
+#define REGCTRLREG4 0x4
+#define MINRESMASKREG 0x618
+#define MAXRESMASKREG 0x61c
+#define CHIPCTRLADDR 0x650
+#define CHIPCTRLDATA 0x654
+#define RSRCTABLEADDR 0x620
+#define RSRCUPDWNTIME 0x628
+#define PMUREG_RESREQ_MASK 0x68c
+
+extern void si_update_masks(si_t *sih);
+
+extern void si_force_islanding(si_t *sih, bool enable);
+
+extern uint32 si_pmu_res_req_timer_clr(si_t *sih);
+extern void si_pmu_rfldo(si_t *sih, bool on);
+extern void si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 spert_val);
+extern void si_pcie_ltr_war(si_t *sih);
+extern uint si_jtag_ureg_read(si_t *sih, uint num);
+extern void si_jtag_ureg_write(si_t *sih, uint num, uint data);
+extern uint si_bbpll_war(si_t *sih, uint state);
+#endif
diff --git a/src/include/typedefs.h b/src/include/typedefs.h
new file mode 100644
index 0000000..d26ab14
--- /dev/null
+++ b/src/include/typedefs.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * $Id: typedefs.h 382996 2013-02-05 06:55:24Z $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#if defined(__x86_64__)
+#define TYPEDEF_UINTPTR
+typedef unsigned long long int uintptr;
+#endif
+
+#if defined(__sparc__)
+#define TYPEDEF_ULONG
+#endif
+
+#if defined(LINUX_PORT)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
+#define TYPEDEF_BOOL
+#endif
+
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18))
+#include <linux/compiler.h>
+#endif
+#endif
+#endif
+
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif
+
+#if !defined(__BOB__)
+
+#if defined(__KERNEL__)
+
+#if defined(LINUX_PORT)
+#include <linux/types.h>
+#endif
+
+#else
+
+#include <sys/types.h>
+
+#endif
+
+#endif
+
+#define USE_TYPEDEF_DEFAULTS
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef unsigned char bool;
+#endif
+
+#ifndef TYPEDEF_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef TYPEDEF_USHORT
+typedef unsigned short ushort;
+#endif
+
+#ifndef TYPEDEF_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef TYPEDEF_ULONG
+typedef unsigned long ulong;
+#endif
+
+#ifndef TYPEDEF_UINT8
+typedef unsigned char uint8;
+#endif
+
+#ifndef TYPEDEF_UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef TYPEDEF_UINT32
+typedef unsigned int uint32;
+#endif
+
+#ifndef TYPEDEF_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#ifndef TYPEDEF_UINTPTR
+typedef unsigned int uintptr;
+#endif
+
+#ifndef TYPEDEF_INT8
+typedef signed char int8;
+#endif
+
+#ifndef TYPEDEF_INT16
+typedef signed short int16;
+#endif
+
+#ifndef TYPEDEF_INT32
+typedef signed int int32;
+#endif
+
+#ifndef TYPEDEF_INT64
+typedef signed long long int64;
+#endif
+
+#ifndef TYPEDEF_FLOAT32
+typedef float float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double float64;
+#endif
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else
+typedef float64 float_t;
+#endif
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1
+#endif
+
+#define AUTO (-1)
+
+#ifndef PTRSZ
+#define PTRSZ sizeof(char*)
+#endif
+
+#if defined(__GNUC__) || defined(__lint)
+ #define BWL_COMPILER_GNU
+#elif defined(__CC_ARM) && __CC_ARM
+ #define BWL_COMPILER_ARMCC
+#else
+ #error "Unknown compiler!"
+#endif
+
+#ifndef INLINE
+ #if defined(BWL_COMPILER_MICROSOFT)
+ #define INLINE __inline
+ #elif defined(BWL_COMPILER_GNU)
+ #define INLINE __inline__
+ #elif defined(BWL_COMPILER_ARMCC)
+ #define INLINE __inline
+ #else
+ #define INLINE
+ #endif
+#endif
+
+#undef TYPEDEF_BOOL
+#undef TYPEDEF_UCHAR
+#undef TYPEDEF_USHORT
+#undef TYPEDEF_UINT
+#undef TYPEDEF_ULONG
+#undef TYPEDEF_UINT8
+#undef TYPEDEF_UINT16
+#undef TYPEDEF_UINT32
+#undef TYPEDEF_UINT64
+#undef TYPEDEF_UINTPTR
+#undef TYPEDEF_INT8
+#undef TYPEDEF_INT16
+#undef TYPEDEF_INT32
+#undef TYPEDEF_INT64
+#undef TYPEDEF_FLOAT32
+#undef TYPEDEF_FLOAT64
+#undef TYPEDEF_FLOAT_T
+
+#endif
+
+#define UNUSED_PARAMETER(x) (void)(x)
+
+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
+
+#include <bcmdefs.h>
+#endif
diff --git a/src/include/wlioctl.h b/src/include/wlioctl.h
new file mode 100644
index 0000000..2c05c7c
--- /dev/null
+++ b/src/include/wlioctl.h
@@ -0,0 +1,1165 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlioctl.h 464835 2014-03-26 01:35:40Z $
+ */
+
+#ifndef _wlioctl_h_
+#define _wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmip.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+#include <bcmwifi_channels.h>
+#include <bcmwifi_rates.h>
+
+#define BWL_DEFAULT_PACKING
+#include <packed_section_start.h>
+
+#define WL_BSS_INFO_VERSION 109
+
+typedef struct wl_bss_info {
+ uint32 version;
+ uint32 length;
+ struct ether_addr BSSID;
+ uint16 beacon_period;
+ uint16 capability;
+ uint8 SSID_len;
+ uint8 SSID[32];
+ struct {
+ uint count;
+ uint8 rates[16];
+ } rateset;
+ chanspec_t chanspec;
+ uint16 atim_window;
+ uint8 dtim_period;
+ int16 RSSI;
+ int8 phy_noise;
+
+ uint8 n_cap;
+ uint32 nbss_cap;
+ uint8 ctl_ch;
+ uint8 padding1[3];
+ uint16 vht_rxmcsmap;
+ uint16 vht_txmcsmap;
+ uint8 flags;
+ uint8 vht_cap;
+ uint8 reserved[2];
+ uint8 basic_mcs[MCSSET_LEN];
+
+ uint16 ie_offset;
+ uint32 ie_length;
+ int16 SNR;
+
+} wl_bss_info_t;
+
+#define WL_BSS_FLAGS_FROM_BEACON 0x01
+#define WL_BSS_FLAGS_FROM_CACHE 0x02
+#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04
+
+#define VHT_BI_SGI_80MHZ 0x00000100
+#define VHT_BI_80MHZ 0x00000200
+#define VHT_BI_160MHZ 0x00000400
+#define VHT_BI_8080MHZ 0x00000800
+
+typedef struct wlc_ssid {
+ uint32 SSID_len;
+ uchar SSID[32];
+} wlc_ssid_t;
+
+typedef struct wl_scan_results {
+ uint32 buflen;
+ uint32 version;
+ uint32 count;
+ wl_bss_info_t bss_info[1];
+} wl_scan_results_t;
+
+#define WL_MAXRATES_IN_SET 16
+typedef struct wl_rateset {
+ uint32 count;
+ uint8 rates[WL_MAXRATES_IN_SET];
+} wl_rateset_t;
+
+typedef struct wl_rateset_args {
+ uint32 count;
+ uint8 rates[WL_MAXRATES_IN_SET];
+ uint8 mcs[MCSSET_LEN];
+ uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX];
+} wl_rateset_args_t;
+
+#define TXBF_RATE_MCS_ALL 4
+#define TXBF_RATE_VHT_ALL 4
+#define TXBF_RATE_OFDM_ALL 8
+
+typedef struct wl_txbf_rateset {
+ uint8 txbf_rate_mcs[TXBF_RATE_MCS_ALL];
+ uint8 txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL];
+ uint16 txbf_rate_vht[TXBF_RATE_VHT_ALL];
+ uint16 txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL];
+ uint8 txbf_rate_ofdm[TXBF_RATE_OFDM_ALL];
+ uint8 txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL];
+ uint8 txbf_rate_ofdm_cnt;
+ uint8 txbf_rate_ofdm_cnt_bcm;
+} wl_txbf_rateset_t;
+
+#define OFDM_RATE_MASK 0x0000007f
+typedef uint8 ofdm_rates_t;
+
+typedef struct wl_uint32_list {
+
+ uint32 count;
+
+ uint32 element[1];
+} wl_uint32_list_t;
+
+typedef struct wl_assoc_params {
+ struct ether_addr bssid;
+ int32 chanspec_num;
+ chanspec_t chanspec_list[1];
+} wl_assoc_params_t;
+#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list)
+
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+typedef wl_assoc_params_t wl_join_assoc_params_t;
+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+typedef struct wl_join_params {
+ wlc_ssid_t ssid;
+ wl_assoc_params_t params;
+} wl_join_params_t;
+
+#define WLC_CNTRY_BUF_SZ 4
+
+#define CRYPTO_ALGO_OFF 0
+#define CRYPTO_ALGO_WEP1 1
+#define CRYPTO_ALGO_TKIP 2
+#define CRYPTO_ALGO_WEP128 3
+#define CRYPTO_ALGO_AES_CCM 4
+#define CRYPTO_ALGO_AES_OCB_MSDU 5
+#define CRYPTO_ALGO_AES_OCB_MPDU 6
+#define CRYPTO_ALGO_NALG 7
+#define CRYPTO_ALGO_PMK 12
+#define CRYPTO_ALGO_BIP 13
+
+#define WSEC_GEN_MIC_ERROR 0x0001
+#define WSEC_GEN_REPLAY 0x0002
+#define WSEC_GEN_ICV_ERROR 0x0004
+#define WSEC_GEN_MFP_ACT_ERROR 0x0008
+#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010
+#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020
+
+#define WL_SOFT_KEY (1 << 0)
+#define WL_PRIMARY_KEY (1 << 1)
+#define WL_KF_RES_4 (1 << 4)
+#define WL_KF_RES_5 (1 << 5)
+#define WL_IBSS_PEER_GROUP_KEY (1 << 6)
+
+typedef struct wl_wsec_key {
+ uint32 index;
+ uint32 len;
+ uint8 data[DOT11_MAX_KEY_SIZE];
+ uint32 pad_1[18];
+ uint32 algo;
+ uint32 flags;
+ uint32 pad_2[2];
+ int pad_3;
+ int iv_initialized;
+ int pad_4;
+
+ struct {
+ uint32 hi;
+ uint16 lo;
+ } rxiv;
+ uint32 pad_5[2];
+ struct ether_addr ea;
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN 8
+#define WSEC_MAX_PSK_LEN 64
+
+#define WSEC_PASSPHRASE (1<<0)
+
+typedef struct {
+ ushort key_len;
+ ushort flags;
+ uint8 key[WSEC_MAX_PSK_LEN];
+} wsec_pmk_t;
+
+#define WEP_ENABLED 0x0001
+#define TKIP_ENABLED 0x0002
+#define AES_ENABLED 0x0004
+#define WSEC_SWFLAG 0x0008
+#define SES_OW_ENABLED 0x0040
+
+#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED)
+
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED)
+
+#define MFP_CAPABLE 0x0200
+#define MFP_REQUIRED 0x0400
+#define MFP_SHA256 0x0800
+
+#define WPA_AUTH_DISABLED 0x0000
+#define WPA_AUTH_NONE 0x0001
+#define WPA_AUTH_UNSPECIFIED 0x0002
+#define WPA_AUTH_PSK 0x0004
+
+#define WPA2_AUTH_UNSPECIFIED 0x0040
+#define WPA2_AUTH_PSK 0x0080
+#define BRCM_AUTH_PSK 0x0100
+#define BRCM_AUTH_DPT 0x0200
+#define WPA2_AUTH_MFP 0x1000
+#define WPA2_AUTH_TPK 0x2000
+#define WPA2_AUTH_FT 0x4000
+#define WPA_AUTH_PFN_ANY 0xffffffff
+
+#define MAXPMKID 16
+
+typedef struct _pmkid {
+ struct ether_addr BSSID;
+ uint8 PMKID[WPA2_PMKID_LEN];
+} pmkid_t;
+
+typedef struct _pmkid_list {
+ uint32 npmkid;
+ pmkid_t pmkid[1];
+} pmkid_list_t;
+
+typedef struct _pmkid_cand {
+ struct ether_addr BSSID;
+ uint8 preauth;
+} pmkid_cand_t;
+
+typedef struct _pmkid_cand_list {
+ uint32 npmkid_cand;
+ pmkid_cand_t pmkid_cand[1];
+} pmkid_cand_list_t;
+
+typedef struct {
+ uint32 val;
+ struct ether_addr ea;
+} scb_val_t;
+
+typedef struct {
+ uint32 code;
+ scb_val_t ioctl_args;
+} authops_t;
+
+typedef struct channel_info {
+ int hw_channel;
+ int target_channel;
+ int scan_channel;
+} channel_info_t;
+
+struct maclist {
+ uint count;
+ struct ether_addr ea[1];
+};
+
+typedef struct wl_ioctl {
+ uint cmd;
+ void *buf;
+ uint len;
+ uint8 set;
+ uint used;
+ uint needed;
+} wl_ioctl_t;
+
+#define ioctl_subtype set
+#define ioctl_pid used
+#define ioctl_status needed
+
+typedef struct wlc_rev_info {
+ uint vendorid;
+ uint deviceid;
+ uint radiorev;
+ uint chiprev;
+ uint corerev;
+ uint boardid;
+ uint boardvendor;
+ uint boardrev;
+ uint driverrev;
+ uint ucoderev;
+ uint bus;
+ uint chipnum;
+ uint phytype;
+ uint phyrev;
+ uint anarev;
+ uint chippkg;
+ uint nvramrev;
+} wlc_rev_info_t;
+
+#define WL_REV_INFO_LEGACY_LENGTH 48
+
+#define WLC_IOCTL_MAXLEN 8192
+#define WLC_IOCTL_SMLEN 256
+#define WLC_IOCTL_MEDLEN 1536
+#if defined(LCNCONF) || defined(LCN40CONF)
+#define WLC_SAMPLECOLLECT_MAXLEN 8192
+#else
+#define WLC_SAMPLECOLLECT_MAXLEN 10240
+#endif
+#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192
+
+#define WLC_GET_MAGIC 0
+#define WLC_GET_VERSION 1
+#define WLC_UP 2
+#define WLC_DOWN 3
+#define WLC_GET_LOOP 4
+#define WLC_SET_LOOP 5
+#define WLC_DUMP 6
+#define WLC_GET_MSGLEVEL 7
+#define WLC_SET_MSGLEVEL 8
+#define WLC_GET_PROMISC 9
+#define WLC_SET_PROMISC 10
+
+#define WLC_GET_RATE 12
+#define WLC_GET_MAX_RATE 13
+#define WLC_GET_INSTANCE 14
+
+#define WLC_GET_INFRA 19
+#define WLC_SET_INFRA 20
+#define WLC_GET_AUTH 21
+#define WLC_SET_AUTH 22
+#define WLC_GET_BSSID 23
+#define WLC_SET_BSSID 24
+#define WLC_GET_SSID 25
+#define WLC_SET_SSID 26
+#define WLC_RESTART 27
+#define WLC_TERMINATED 28
+
+#define WLC_GET_CHANNEL 29
+#define WLC_SET_CHANNEL 30
+#define WLC_GET_SRL 31
+#define WLC_SET_SRL 32
+#define WLC_GET_LRL 33
+#define WLC_SET_LRL 34
+#define WLC_GET_PLCPHDR 35
+#define WLC_SET_PLCPHDR 36
+#define WLC_GET_RADIO 37
+#define WLC_SET_RADIO 38
+#define WLC_GET_PHYTYPE 39
+#define WLC_DUMP_RATE 40
+#define WLC_SET_RATE_PARAMS 41
+#define WLC_GET_FIXRATE 42
+#define WLC_SET_FIXRATE 43
+
+#define WLC_GET_KEY 44
+#define WLC_SET_KEY 45
+#define WLC_GET_REGULATORY 46
+#define WLC_SET_REGULATORY 47
+#define WLC_GET_PASSIVE_SCAN 48
+#define WLC_SET_PASSIVE_SCAN 49
+#define WLC_SCAN 50
+#define WLC_SCAN_RESULTS 51
+#define WLC_DISASSOC 52
+#define WLC_REASSOC 53
+#define WLC_GET_ROAM_TRIGGER 54
+#define WLC_SET_ROAM_TRIGGER 55
+#define WLC_GET_ROAM_DELTA 56
+#define WLC_SET_ROAM_DELTA 57
+#define WLC_GET_ROAM_SCAN_PERIOD 58
+#define WLC_SET_ROAM_SCAN_PERIOD 59
+#define WLC_EVM 60
+#define WLC_GET_TXANT 61
+#define WLC_SET_TXANT 62
+#define WLC_GET_ANTDIV 63
+#define WLC_SET_ANTDIV 64
+
+#define WLC_GET_CLOSED 67
+#define WLC_SET_CLOSED 68
+#define WLC_GET_MACLIST 69
+#define WLC_SET_MACLIST 70
+#define WLC_GET_RATESET 71
+#define WLC_SET_RATESET 72
+
+#define WLC_LONGTRAIN 74
+#define WLC_GET_BCNPRD 75
+#define WLC_SET_BCNPRD 76
+#define WLC_GET_DTIMPRD 77
+#define WLC_SET_DTIMPRD 78
+#define WLC_GET_SROM 79
+#define WLC_SET_SROM 80
+#define WLC_GET_WEP_RESTRICT 81
+#define WLC_SET_WEP_RESTRICT 82
+#define WLC_GET_COUNTRY 83
+#define WLC_SET_COUNTRY 84
+#define WLC_GET_PM 85
+#define WLC_SET_PM 86
+#define WLC_GET_WAKE 87
+#define WLC_SET_WAKE 88
+
+#define WLC_GET_FORCELINK 90
+#define WLC_SET_FORCELINK 91
+#define WLC_FREQ_ACCURACY 92
+#define WLC_CARRIER_SUPPRESS 93
+#define WLC_GET_PHYREG 94
+#define WLC_SET_PHYREG 95
+#define WLC_GET_RADIOREG 96
+#define WLC_SET_RADIOREG 97
+#define WLC_GET_REVINFO 98
+#define WLC_GET_UCANTDIV 99
+#define WLC_SET_UCANTDIV 100
+#define WLC_R_REG 101
+#define WLC_W_REG 102
+
+#define WLC_GET_MACMODE 105
+#define WLC_SET_MACMODE 106
+#define WLC_GET_MONITOR 107
+#define WLC_SET_MONITOR 108
+#define WLC_GET_GMODE 109
+#define WLC_SET_GMODE 110
+#define WLC_GET_LEGACY_ERP 111
+#define WLC_SET_LEGACY_ERP 112
+#define WLC_GET_RX_ANT 113
+#define WLC_GET_CURR_RATESET 114
+#define WLC_GET_SCANSUPPRESS 115
+#define WLC_SET_SCANSUPPRESS 116
+#define WLC_GET_AP 117
+#define WLC_SET_AP 118
+#define WLC_GET_EAP_RESTRICT 119
+#define WLC_SET_EAP_RESTRICT 120
+#define WLC_SCB_AUTHORIZE 121
+#define WLC_SCB_DEAUTHORIZE 122
+#define WLC_GET_WDSLIST 123
+#define WLC_SET_WDSLIST 124
+#define WLC_GET_ATIM 125
+#define WLC_SET_ATIM 126
+#define WLC_GET_RSSI 127
+#define WLC_GET_PHYANTDIV 128
+#define WLC_SET_PHYANTDIV 129
+#define WLC_AP_RX_ONLY 130
+#define WLC_GET_TX_PATH_PWR 131
+#define WLC_SET_TX_PATH_PWR 132
+#define WLC_GET_WSEC 133
+#define WLC_SET_WSEC 134
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_PKTCNTS 137
+#define WLC_GET_LAZYWDS 138
+#define WLC_SET_LAZYWDS 139
+#define WLC_GET_BANDLIST 140
+
+#define WLC_GET_PHYLIST 180
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201
+#define WLC_GET_VALID_CHANNELS 217
+#define WLC_GET_FAKEFRAG 218
+#define WLC_SET_FAKEFRAG 219
+#define WLC_GET_PWROUT_PERCENTAGE 220
+#define WLC_SET_PWROUT_PERCENTAGE 221
+#define WLC_SET_BAD_FRAME_PREEMPT 222
+#define WLC_GET_BAD_FRAME_PREEMPT 223
+#define WLC_SET_LEAP_LIST 224
+#define WLC_GET_LEAP_LIST 225
+#define WLC_GET_CWMIN 226
+#define WLC_SET_CWMIN 227
+#define WLC_GET_CWMAX 228
+#define WLC_SET_CWMAX 229
+#define WLC_GET_WET 230
+#define WLC_SET_WET 231
+#define WLC_GET_PUB 232
+
+#define WLC_GET_KEY_PRIMARY 235
+#define WLC_SET_KEY_PRIMARY 236
+
+#define WLC_GET_VAR 262
+#define WLC_SET_VAR 263
+
+#define WL_RADIO_SW_DISABLE (1<<0)
+#define WL_RADIO_HW_DISABLE (1<<1)
+#define WL_RADIO_MPC_DISABLE (1<<2)
+#define WL_RADIO_COUNTRY_DISABLE (1<<3)
+
+#define WL_SPURAVOID_OFF 0
+#define WL_SPURAVOID_ON1 1
+#define WL_SPURAVOID_ON2 2
+
+#define WL_4335_SPURAVOID_ON1 1
+#define WL_4335_SPURAVOID_ON2 2
+#define WL_4335_SPURAVOID_ON3 3
+#define WL_4335_SPURAVOID_ON4 4
+#define WL_4335_SPURAVOID_ON5 5
+#define WL_4335_SPURAVOID_ON6 6
+#define WL_4335_SPURAVOID_ON7 7
+#define WL_4335_SPURAVOID_ON8 8
+#define WL_4335_SPURAVOID_ON9 9
+
+#define WL_TXPWR_OVERRIDE (1U<<31)
+#define WL_TXPWR_NEG (1U<<30)
+
+#define WLC_PHY_TYPE_A 0
+#define WLC_PHY_TYPE_B 1
+#define WLC_PHY_TYPE_G 2
+#define WLC_PHY_TYPE_N 4
+#define WLC_PHY_TYPE_LP 5
+#define WLC_PHY_TYPE_SSN 6
+#define WLC_PHY_TYPE_HT 7
+#define WLC_PHY_TYPE_LCN 8
+#define WLC_PHY_TYPE_LCN40 10
+#define WLC_PHY_TYPE_AC 11
+#define WLC_PHY_TYPE_NULL 0xf
+
+#define PM_OFF 0
+#define PM_MAX 1
+#define PM_FAST 2
+#define PM_FORCE_OFF 3
+
+#define NFIFO 6
+#define NREINITREASONCOUNT 8
+#define REINITREASONIDX(_x) (((_x) < NREINITREASONCOUNT) ? (_x) : 0)
+
+#define WL_CNT_T_VERSION 10
+
+typedef struct {
+ uint16 version;
+ uint16 length;
+
+ uint32 txframe;
+ uint32 txbyte;
+ uint32 txretrans;
+ uint32 txerror;
+ uint32 txctl;
+ uint32 txprshort;
+ uint32 txserr;
+ uint32 txnobuf;
+ uint32 txnoassoc;
+ uint32 txrunt;
+ uint32 txchit;
+ uint32 txcmiss;
+
+ uint32 txuflo;
+ uint32 txphyerr;
+ uint32 txphycrs;
+
+ uint32 rxframe;
+ uint32 rxbyte;
+ uint32 rxerror;
+ uint32 rxctl;
+ uint32 rxnobuf;
+ uint32 rxnondata;
+ uint32 rxbadds;
+ uint32 rxbadcm;
+ uint32 rxfragerr;
+ uint32 rxrunt;
+ uint32 rxgiant;
+ uint32 rxnoscb;
+ uint32 rxbadproto;
+ uint32 rxbadsrcmac;
+ uint32 rxbadda;
+ uint32 rxfilter;
+
+ uint32 rxoflo;
+ uint32 rxuflo[NFIFO];
+
+ uint32 d11cnt_txrts_off;
+ uint32 d11cnt_rxcrc_off;
+ uint32 d11cnt_txnocts_off;
+
+ uint32 dmade;
+ uint32 dmada;
+ uint32 dmape;
+ uint32 reset;
+ uint32 tbtt;
+ uint32 txdmawar;
+ uint32 pkt_callback_reg_fail;
+
+ uint32 txallfrm;
+ uint32 txrtsfrm;
+ uint32 txctsfrm;
+ uint32 txackfrm;
+ uint32 txdnlfrm;
+ uint32 txbcnfrm;
+ uint32 txfunfl[8];
+ uint32 txtplunfl;
+ uint32 txphyerror;
+ uint32 rxfrmtoolong;
+ uint32 rxfrmtooshrt;
+ uint32 rxinvmachdr;
+ uint32 rxbadfcs;
+ uint32 rxbadplcp;
+ uint32 rxcrsglitch;
+ uint32 rxstrt;
+ uint32 rxdfrmucastmbss;
+ uint32 rxmfrmucastmbss;
+ uint32 rxcfrmucast;
+ uint32 rxrtsucast;
+ uint32 rxctsucast;
+ uint32 rxackucast;
+ uint32 rxdfrmocast;
+ uint32 rxmfrmocast;
+ uint32 rxcfrmocast;
+ uint32 rxrtsocast;
+ uint32 rxctsocast;
+ uint32 rxdfrmmcast;
+ uint32 rxmfrmmcast;
+ uint32 rxcfrmmcast;
+ uint32 rxbeaconmbss;
+ uint32 rxdfrmucastobss;
+ uint32 rxbeaconobss;
+ uint32 rxrsptmout;
+ uint32 bcntxcancl;
+ uint32 rxf0ovfl;
+ uint32 rxf1ovfl;
+ uint32 rxf2ovfl;
+ uint32 txsfovfl;
+ uint32 pmqovfl;
+ uint32 rxcgprqfrm;
+ uint32 rxcgprsqovfl;
+ uint32 txcgprsfail;
+ uint32 txcgprssuc;
+ uint32 prs_timeout;
+ uint32 rxnack;
+ uint32 frmscons;
+ uint32 txnack;
+ uint32 txglitch_nack;
+ uint32 txburst;
+
+ uint32 txfrag;
+ uint32 txmulti;
+ uint32 txfail;
+ uint32 txretry;
+ uint32 txretrie;
+ uint32 rxdup;
+ uint32 txrts;
+ uint32 txnocts;
+ uint32 txnoack;
+ uint32 rxfrag;
+ uint32 rxmulti;
+ uint32 rxcrc;
+ uint32 txfrmsnt;
+ uint32 rxundec;
+
+ uint32 tkipmicfaill;
+ uint32 tkipcntrmsr;
+ uint32 tkipreplay;
+ uint32 ccmpfmterr;
+ uint32 ccmpreplay;
+ uint32 ccmpundec;
+ uint32 fourwayfail;
+ uint32 wepundec;
+ uint32 wepicverr;
+ uint32 decsuccess;
+ uint32 tkipicverr;
+ uint32 wepexcluded;
+
+ uint32 txchanrej;
+ uint32 psmwds;
+ uint32 phywatchdog;
+
+ uint32 prq_entries_handled;
+ uint32 prq_undirected_entries;
+ uint32 prq_bad_entries;
+ uint32 atim_suppress_count;
+ uint32 bcn_template_not_ready;
+ uint32 bcn_template_not_ready_done;
+ uint32 late_tbtt_dpc;
+
+ uint32 rx1mbps;
+ uint32 rx2mbps;
+ uint32 rx5mbps5;
+ uint32 rx6mbps;
+ uint32 rx9mbps;
+ uint32 rx11mbps;
+ uint32 rx12mbps;
+ uint32 rx18mbps;
+ uint32 rx24mbps;
+ uint32 rx36mbps;
+ uint32 rx48mbps;
+ uint32 rx54mbps;
+ uint32 rx108mbps;
+ uint32 rx162mbps;
+ uint32 rx216mbps;
+ uint32 rx270mbps;
+ uint32 rx324mbps;
+ uint32 rx378mbps;
+ uint32 rx432mbps;
+ uint32 rx486mbps;
+ uint32 rx540mbps;
+
+ uint32 pktengrxducast;
+ uint32 pktengrxdmcast;
+
+ uint32 rfdisable;
+ uint32 bphy_rxcrsglitch;
+ uint32 bphy_badplcp;
+
+ uint32 txexptime;
+
+ uint32 txmpdu_sgi;
+ uint32 rxmpdu_sgi;
+ uint32 txmpdu_stbc;
+ uint32 rxmpdu_stbc;
+
+ uint32 rxundec_mcst;
+
+ uint32 tkipmicfaill_mcst;
+ uint32 tkipcntrmsr_mcst;
+ uint32 tkipreplay_mcst;
+ uint32 ccmpfmterr_mcst;
+ uint32 ccmpreplay_mcst;
+ uint32 ccmpundec_mcst;
+ uint32 fourwayfail_mcst;
+ uint32 wepundec_mcst;
+ uint32 wepicverr_mcst;
+ uint32 decsuccess_mcst;
+ uint32 tkipicverr_mcst;
+ uint32 wepexcluded_mcst;
+
+ uint32 dma_hang;
+ uint32 reinit;
+
+ uint32 pstatxucast;
+ uint32 pstatxnoassoc;
+ uint32 pstarxucast;
+ uint32 pstarxbcmc;
+ uint32 pstatxbcmc;
+
+ uint32 cso_passthrough;
+ uint32 cso_normal;
+ uint32 chained;
+ uint32 chainedsz1;
+ uint32 unchained;
+ uint32 maxchainsz;
+ uint32 currchainsz;
+ uint32 pciereset;
+ uint32 cfgrestore;
+ uint32 reinitreason[NREINITREASONCOUNT];
+} wl_cnt_t;
+
+typedef struct {
+ bool auto_en;
+ uint8 active_ant;
+ uint32 rxcount;
+ int16 avg_snr_per_ant0;
+ int16 avg_snr_per_ant1;
+ uint32 swap_ge_rxcount0;
+ uint32 swap_ge_rxcount1;
+ uint32 swap_ge_snrthresh0;
+ uint32 swap_ge_snrthresh1;
+ uint32 swap_txfail0;
+ uint32 swap_txfail1;
+ uint32 swap_timer0;
+ uint32 swap_timer1;
+ uint32 swap_alivecheck0;
+ uint32 swap_alivecheck1;
+ uint32 rxcount_per_ant0;
+ uint32 rxcount_per_ant1;
+ uint32 acc_rxcount;
+ uint32 acc_rxcount_per_ant0;
+ uint32 acc_rxcount_per_ant1;
+} wlc_swdiv_stats_t;
+
+#define WL_WME_CNT_VERSION 1
+
+typedef struct {
+ uint32 packets;
+ uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+ uint16 version;
+ uint16 length;
+
+ wl_traffic_stats_t tx[AC_COUNT];
+ wl_traffic_stats_t tx_failed[AC_COUNT];
+ wl_traffic_stats_t rx[AC_COUNT];
+ wl_traffic_stats_t rx_failed[AC_COUNT];
+
+ wl_traffic_stats_t forward[AC_COUNT];
+
+ wl_traffic_stats_t tx_expired[AC_COUNT];
+
+} wl_wme_cnt_t;
+
+typedef struct wl_mkeep_alive_pkt {
+ uint16 version;
+ uint16 length;
+ uint32 period_msec;
+ uint16 len_bytes;
+ uint8 keep_alive_id;
+ uint8 data[1];
+} wl_mkeep_alive_pkt_t;
+
+#define WL_MKEEP_ALIVE_VERSION 1
+#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data)
+#define WL_MKEEP_ALIVE_PRECISION 500
+
+typedef struct wl_mtcpkeep_alive_conn_pkt {
+ struct ether_addr saddr;
+ struct ether_addr daddr;
+ struct ipv4_addr sipaddr;
+ struct ipv4_addr dipaddr;
+ uint16 sport;
+ uint16 dport;
+ uint32 seq;
+ uint32 ack;
+ uint16 tcpwin;
+} wl_mtcpkeep_alive_conn_pkt_t;
+
+typedef struct wl_mtcpkeep_alive_timers_pkt {
+ uint16 interval;
+ uint16 retry_interval;
+ uint16 retry_count;
+} wl_mtcpkeep_alive_timers_pkt_t;
+
+#ifndef ETHER_MAX_DATA
+#define ETHER_MAX_DATA 1500
+#endif
+
+typedef struct wake_info {
+ uint32 wake_reason;
+ uint32 wake_info_len;
+ uchar packet[1];
+} wake_info_t;
+
+typedef struct wake_pkt {
+ uint32 wake_pkt_len;
+ uchar packet[1];
+} wake_pkt_t;
+
+#define WL_MTCPKEEP_ALIVE_VERSION 1
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION 1
+
+typedef struct wlc_ba_cnt {
+ uint16 version;
+ uint16 length;
+
+ uint32 txpdu;
+ uint32 txsdu;
+ uint32 txfc;
+ uint32 txfci;
+ uint32 txretrans;
+ uint32 txbatimer;
+ uint32 txdrop;
+ uint32 txaddbareq;
+ uint32 txaddbaresp;
+ uint32 txdelba;
+ uint32 txba;
+ uint32 txbar;
+ uint32 txpad[4];
+
+ uint32 rxpdu;
+ uint32 rxqed;
+ uint32 rxdup;
+ uint32 rxnobuf;
+ uint32 rxaddbareq;
+ uint32 rxaddbaresp;
+ uint32 rxdelba;
+ uint32 rxba;
+ uint32 rxbar;
+ uint32 rxinvba;
+ uint32 rxbaholes;
+ uint32 rxunexp;
+ uint32 rxpad[4];
+} wlc_ba_cnt_t;
+#endif
+
+struct ampdu_tid_control {
+ uint8 tid;
+ uint8 enable;
+};
+
+struct ampdu_ea_tid {
+ struct ether_addr ea;
+ uint8 tid;
+};
+
+struct ampdu_retry_tid {
+ uint8 tid;
+ uint8 retry;
+};
+
+#define TOE_TX_CSUM_OL 0x00000001
+#define TOE_RX_CSUM_OL 0x00000002
+
+#define TOE_ERRTEST_TX_CSUM 0x00000001
+#define TOE_ERRTEST_RX_CSUM 0x00000002
+#define TOE_ERRTEST_RX_CSUM2 0x00000004
+
+struct toe_ol_stats_t {
+
+ uint32 tx_summed;
+
+ uint32 tx_iph_fill;
+ uint32 tx_tcp_fill;
+ uint32 tx_udp_fill;
+ uint32 tx_icmp_fill;
+
+ uint32 rx_iph_good;
+ uint32 rx_iph_bad;
+ uint32 rx_tcp_good;
+ uint32 rx_tcp_bad;
+ uint32 rx_udp_good;
+ uint32 rx_udp_bad;
+ uint32 rx_icmp_good;
+ uint32 rx_icmp_bad;
+
+ uint32 tx_tcp_errinj;
+ uint32 tx_udp_errinj;
+ uint32 tx_icmp_errinj;
+
+ uint32 rx_tcp_errinj;
+ uint32 rx_udp_errinj;
+ uint32 rx_icmp_errinj;
+};
+
+#define ARP_OL_AGENT 0x00000001
+#define ARP_OL_SNOOP 0x00000002
+#define ARP_OL_HOST_AUTO_REPLY 0x00000004
+#define ARP_OL_PEER_AUTO_REPLY 0x00000008
+
+#define ARP_ERRTEST_REPLY_PEER 0x1
+#define ARP_ERRTEST_REPLY_HOST 0x2
+
+#define ARP_MULTIHOMING_MAX 8
+#define ND_MULTIHOMING_MAX 10
+
+struct arp_ol_stats_t {
+ uint32 host_ip_entries;
+ uint32 host_ip_overflow;
+
+ uint32 arp_table_entries;
+ uint32 arp_table_overflow;
+
+ uint32 host_request;
+ uint32 host_reply;
+ uint32 host_service;
+
+ uint32 peer_request;
+ uint32 peer_request_drop;
+ uint32 peer_reply;
+ uint32 peer_reply_drop;
+ uint32 peer_service;
+};
+
+struct nd_ol_stats_t {
+ uint32 host_ip_entries;
+ uint32 host_ip_overflow;
+ uint32 peer_request;
+ uint32 peer_request_drop;
+ uint32 peer_reply_drop;
+ uint32 peer_service;
+};
+
+typedef struct wl_keep_alive_pkt {
+ uint32 period_msec;
+ uint16 len_bytes;
+ uint8 data[1];
+} wl_keep_alive_pkt_t;
+
+#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data)
+
+typedef enum wl_pkt_filter_type {
+ WL_PKT_FILTER_TYPE_PATTERN_MATCH
+} wl_pkt_filter_type_t;
+
+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
+
+typedef struct wl_pkt_filter_pattern {
+ uint32 offset;
+ uint32 size_bytes;
+ uint8 mask_and_pattern[1];
+
+} wl_pkt_filter_pattern_t;
+
+typedef struct wl_pkt_filter {
+ uint32 id;
+ uint32 type;
+ uint32 negate_match;
+ union {
+ wl_pkt_filter_pattern_t pattern;
+ } u;
+} wl_pkt_filter_t;
+
+typedef struct wl_tcp_keep_set {
+ uint32 val1;
+ uint32 val2;
+} wl_tcp_keep_set_t;
+
+#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u)
+#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern)
+
+typedef struct wl_pkt_filter_enable {
+ uint32 id;
+ uint32 enable;
+} wl_pkt_filter_enable_t;
+
+typedef struct wl_pkt_filter_list {
+ uint32 num;
+ wl_pkt_filter_t filter[1];
+} wl_pkt_filter_list_t;
+
+#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter)
+
+typedef struct wl_pkt_filter_stats {
+ uint32 num_pkts_matched;
+ uint32 num_pkts_forwarded;
+ uint32 num_pkts_discarded;
+} wl_pkt_filter_stats_t;
+
+#define WL_WOWL_MAGIC (1 << 0)
+#define WL_WOWL_NET (1 << 1)
+#define WL_WOWL_DIS (1 << 2)
+#define WL_WOWL_RETR (1 << 3)
+#define WL_WOWL_BCN (1 << 4)
+#define WL_WOWL_TST (1 << 5)
+#define WL_WOWL_M1 (1 << 6)
+#define WL_WOWL_EAPID (1 << 7)
+#define WL_WOWL_PME_GPIO (1 << 8)
+#define WL_WOWL_NEEDTKIP1 (1 << 9)
+#define WL_WOWL_GTK_FAILURE (1 << 10)
+#define WL_WOWL_EXTMAGPAT (1 << 11)
+#define WL_WOWL_ARPOFFLOAD (1 << 12)
+#define WL_WOWL_WPA2 (1 << 13)
+#define WL_WOWL_KEYROT (1 << 14)
+#define WL_WOWL_BCAST (1 << 15)
+#define WL_WOWL_SCANOL (1 << 16)
+#define WL_WOWL_TCPKEEP_TIME (1 << 17)
+#define WL_WOWL_MDNS_CONFLICT (1 << 18)
+#define WL_WOWL_MDNS_SERVICE (1 << 19)
+#define WL_WOWL_TCPKEEP_DATA (1 << 20)
+#define WL_WOWL_FW_HALT (1 << 21)
+#define WL_WOWL_ENAB_HWRADIO (1 << 22)
+#define WL_WOWL_MIC_FAIL (1 << 23)
+#define WL_WOWL_LINKDOWN (1 << 31)
+
+#define MAGIC_PKT_MINLEN 102
+#define MAGIC_PKT_NUM_MAC_ADDRS 16
+
+typedef enum {
+ wowl_pattern_type_bitmap = 0,
+ wowl_pattern_type_arp,
+ wowl_pattern_type_na
+} wowl_pattern_type_t;
+
+typedef struct wl_wowl_pattern {
+ uint32 masksize;
+ uint32 offset;
+ uint32 patternoffset;
+ uint32 patternsize;
+ uint32 id;
+ uint32 reasonsize;
+ wowl_pattern_type_t type;
+
+} wl_wowl_pattern_t;
+
+typedef struct wl_wowl_pattern_list {
+ uint count;
+ wl_wowl_pattern_t pattern[1];
+} wl_wowl_pattern_list_t;
+
+typedef struct wl_wowl_wakeind {
+ uint8 pci_wakeind;
+ uint32 ucode_wakeind;
+} wl_wowl_wakeind_t;
+
+typedef struct {
+ uint32 pktlen;
+ void *sdu;
+} tcp_keepalive_wake_pkt_infop_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct nbr_element {
+ uint8 id;
+ uint8 len;
+ struct ether_addr bssid;
+ uint32 bssid_info;
+ uint8 reg;
+ uint8 channel;
+ uint8 phytype;
+} BWL_POST_PACKED_STRUCT nbr_element_t;
+
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+
+#include <packed_section_end.h>
+
+typedef struct bcnreq {
+ uint8 bcn_mode;
+ int dur;
+ int channel;
+ struct ether_addr da;
+ uint16 random_int;
+ wlc_ssid_t ssid;
+ uint16 reps;
+} bcnreq_t;
+
+typedef struct rrmreq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ uint16 reps;
+} rrmreq_t;
+
+typedef struct framereq {
+ struct ether_addr da;
+ uint8 reg;
+ uint8 chan;
+ uint16 random_int;
+ uint16 dur;
+ struct ether_addr ta;
+ uint16 reps;
+} framereq_t;
+
+typedef struct statreq {
+ struct ether_addr da;
+ struct ether_addr peer;
+ uint16 random_int;
+ uint16 dur;
+ uint8 group_id;
+ uint16 reps;
+} statreq_t;
+
+typedef struct wlc_l2keepalive_ol_params {
+ uint8 flags;
+ uint8 prio;
+ uint16 period_ms;
+} wlc_l2keepalive_ol_params_t;
+
+typedef struct wlc_dwds_config {
+ uint32 mode;
+ struct ether_addr ea;
+} wlc_dwds_config_t;
+
+#define WLC_KCK_LEN 16
+#define WLC_KEK_LEN 16
+#define WLC_REPLAY_CTR_LEN 8
+
+typedef struct wlc_rekey_info {
+ uint32 offload_id;
+ uint8 kek[WLC_KEK_LEN];
+ uint8 kck[WLC_KCK_LEN];
+ uint8 replay_counter[WLC_REPLAY_CTR_LEN];
+} wlc_rekey_info_t;
+
+#endif
diff --git a/src/shared/bcmwifi/include/bcmwifi_channels.h b/src/shared/bcmwifi/include/bcmwifi_channels.h
new file mode 100644
index 0000000..550c4fd
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_channels.h
@@ -0,0 +1,353 @@
+/*
+ * Misc utility routines for WL and Apps
+ * This header file housing the define and function prototype use by
+ * both the wl driver, tools & Apps.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $
+ */
+
+#ifndef _bcmwifi_channels_h_
+#define _bcmwifi_channels_h_
+
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+typedef uint16 chanspec_t;
+
+#define CH_UPPER_SB 0x01
+#define CH_LOWER_SB 0x02
+#define CH_EWA_VALID 0x04
+#define CH_80MHZ_APART 16
+#define CH_40MHZ_APART 8
+#define CH_20MHZ_APART 4
+#define CH_10MHZ_APART 2
+#define CH_5MHZ_APART 1
+#define CH_MAX_2G_CHANNEL 14
+#define MAXCHANNEL 224
+#define MAXCHANNEL_NUM (MAXCHANNEL - 1)
+
+#define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM)
+
+#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \
+ (sep))
+
+#undef D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT 0
+#define WL_CHANSPEC_CHAN1_MASK 0x000f
+#define WL_CHANSPEC_CHAN1_SHIFT 0
+#define WL_CHANSPEC_CHAN2_MASK 0x00f0
+#define WL_CHANSPEC_CHAN2_SHIFT 4
+
+#define WL_CHANSPEC_CTL_SB_MASK 0x0700
+#define WL_CHANSPEC_CTL_SB_SHIFT 8
+#define WL_CHANSPEC_CTL_SB_LLL 0x0000
+#define WL_CHANSPEC_CTL_SB_LLU 0x0100
+#define WL_CHANSPEC_CTL_SB_LUL 0x0200
+#define WL_CHANSPEC_CTL_SB_LUU 0x0300
+#define WL_CHANSPEC_CTL_SB_ULL 0x0400
+#define WL_CHANSPEC_CTL_SB_ULU 0x0500
+#define WL_CHANSPEC_CTL_SB_UUL 0x0600
+#define WL_CHANSPEC_CTL_SB_UUU 0x0700
+#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL
+#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
+#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
+
+#define WL_CHANSPEC_BW_MASK 0x3800
+#define WL_CHANSPEC_BW_SHIFT 11
+#define WL_CHANSPEC_BW_5 0x0000
+#define WL_CHANSPEC_BW_10 0x0800
+#define WL_CHANSPEC_BW_20 0x1000
+#define WL_CHANSPEC_BW_40 0x1800
+#define WL_CHANSPEC_BW_80 0x2000
+#define WL_CHANSPEC_BW_160 0x2800
+#define WL_CHANSPEC_BW_8080 0x3000
+#define WL_CHANSPEC_BW_2P5 0x3800
+
+#define WL_CHANSPEC_BAND_MASK 0xc000
+#define WL_CHANSPEC_BAND_SHIFT 14
+#define WL_CHANSPEC_BAND_2G 0x0000
+#define WL_CHANSPEC_BAND_3G 0x4000
+#define WL_CHANSPEC_BAND_4G 0x8000
+#define WL_CHANSPEC_BAND_5G 0xc000
+#define INVCHANSPEC 255
+#define MAX_CHANSPEC 0xFFFF
+
+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
+ ((channel) - CH_10MHZ_APART) : 0)
+#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
+ ((channel) + CH_10MHZ_APART) : 0)
+
+#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
+#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
+ ((channel) + 3 * CH_10MHZ_APART) : 0)
+#define LU_20_SB(channel) LOWER_20_SB(channel)
+#define UL_20_SB(channel) UPPER_20_SB(channel)
+
+#define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART)
+#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART)
+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
+#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH2P5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH10MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
+ ((channel) + CH_20MHZ_APART) : 0)
+#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
+ WL_CHANSPEC_BAND_5G))
+#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
+#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
+ ((channel) | (ctlsb) | \
+ WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
+#define CHBW_CHSPEC(bw, channel) (chanspec_t)((chanspec_t)(channel) | (bw) | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+
+#ifdef WL11AC_80P80
+#define CHSPEC_CHANNEL(chspec) wf_chspec_channel(chspec)
+#else
+#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#endif
+#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
+#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK)
+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK)
+
+#define CHSPEC_IS2P5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
+#define CHSPEC_IS5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
+#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
+#endif
+
+#ifdef WL11ULB
+
+#define BW_LE20(bw) (((bw) == WL_CHANSPEC_BW_2P5) || \
+ ((bw) == WL_CHANSPEC_BW_5) || \
+ ((bw) == WL_CHANSPEC_BW_10) || \
+ ((bw) == WL_CHANSPEC_BW_20))
+#define CHSPEC_ISLE20(chspec) (CHSPEC_IS2P5(chspec) || CHSPEC_IS5(chspec) || \
+ CHSPEC_IS10(chspec) || CHSPEC_IS20(chspec))
+#else
+#define BW_LE20(bw) ((bw) == WL_CHANSPEC_BW_20)
+#define CHSPEC_ISLE20(chspec) (CHSPEC_IS20(chspec))
+#endif
+
+#define BW_LE40(bw) (BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40))
+#define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80))
+#define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160))
+#define CHSPEC_BW_LE20(chspec) (BW_LE20(CHSPEC_BW(chspec)))
+#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+#define CHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
+
+#define CHANSPEC_STR_LEN 20
+
+#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
+ CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
+
+#ifdef WL11ULB
+#define CHSPEC_BW_GE(chspec, bw) \
+ (((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) >= (bw))) && \
+ (!(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
+#else
+#define CHSPEC_BW_GE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) >= (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_LE(chspec, bw) \
+ (((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) <= (bw))) || \
+ (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5))
+#else
+#define CHSPEC_BW_LE(chspec, bw) \
+ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
+ (CHSPEC_BW(chspec) <= (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_GT(chspec, bw) \
+ ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) > (bw))) && \
+ (CHSPEC_BW(chspec) != WL_CHANSPEC_BW_2P5))
+#else
+#define CHSPEC_BW_GT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) > (bw)))
+#endif
+
+#ifdef WL11ULB
+#define CHSPEC_BW_LT(chspec, bw) \
+ ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) < (bw))) || \
+ ((CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
+#else
+#define CHSPEC_BW_LT(chspec, bw) \
+ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
+ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
+ (CHSPEC_BW(chspec) < (bw)))
+#endif
+
+#define WL_LCHANSPEC_CHAN_MASK 0x00ff
+#define WL_LCHANSPEC_CHAN_SHIFT 0
+
+#define WL_LCHANSPEC_CTL_SB_MASK 0x0300
+#define WL_LCHANSPEC_CTL_SB_SHIFT 8
+#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100
+#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200
+#define WL_LCHANSPEC_CTL_SB_NONE 0x0300
+
+#define WL_LCHANSPEC_BW_MASK 0x0C00
+#define WL_LCHANSPEC_BW_SHIFT 10
+#define WL_LCHANSPEC_BW_10 0x0400
+#define WL_LCHANSPEC_BW_20 0x0800
+#define WL_LCHANSPEC_BW_40 0x0C00
+
+#define WL_LCHANSPEC_BAND_MASK 0xf000
+#define WL_LCHANSPEC_BAND_SHIFT 12
+#define WL_LCHANSPEC_BAND_5G 0x1000
+#define WL_LCHANSPEC_BAND_2G 0x2000
+
+#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
+#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK)
+#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
+#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK)
+#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
+#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
+#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
+#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
+#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
+
+#define LCHSPEC_SB_UPPER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+#define LCHSPEC_SB_LOWER(chspec) \
+ ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
+ (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+
+#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band)))
+
+#define CH20MHZ_LCHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
+ WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
+ WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
+
+#define WF_CHAN_FACTOR_2_4_G 4814
+
+#define WF_CHAN_FACTOR_5_G 10000
+
+#define WF_CHAN_FACTOR_4_G 8000
+
+#define WLC_2G_25MHZ_OFFSET 5
+
+#define WF_NUM_SIDEBANDS_40MHZ 2
+#define WF_NUM_SIDEBANDS_80MHZ 4
+#define WF_NUM_SIDEBANDS_8080MHZ 4
+#define WF_NUM_SIDEBANDS_160MHZ 8
+
+extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
+
+extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
+
+extern chanspec_t wf_chspec_aton(const char *a);
+
+extern bool wf_chspec_malformed(chanspec_t chanspec);
+
+extern bool wf_chspec_valid(chanspec_t chanspec);
+
+extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
+
+extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
+
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
+
+extern int wf_mhz2channel(uint freq, uint start_factor);
+
+extern int wf_channel2mhz(uint channel, uint start_factor);
+
+extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
+
+extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
+
+extern uint wf_channel2freq(uint channel);
+extern uint wf_freq2channel(uint freq);
+
+extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
+ uint8 chan0_80Mhz, uint8 chan1_80Mhz);
+
+extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
+
+extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
+
+extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
+
+#ifdef WL11AC_80P80
+
+extern uint8 wf_chspec_channel(chanspec_t chspec);
+#endif
+#endif
diff --git a/src/shared/bcmwifi/include/bcmwifi_rates.h b/src/shared/bcmwifi/include/bcmwifi_rates.h
new file mode 100644
index 0000000..a2b8009
--- /dev/null
+++ b/src/shared/bcmwifi/include/bcmwifi_rates.h
@@ -0,0 +1,705 @@
+/*
+ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $
+ */
+
+#ifndef _bcmwifi_rates_h_
+#define _bcmwifi_rates_h_
+
+#define WL_RATESET_SZ_DSSS 4
+#define WL_RATESET_SZ_OFDM 8
+#define WL_RATESET_SZ_VHT_MCS 10
+#define WL_RATESET_SZ_VHT_MCS_P 12
+
+#if defined(WLPROPRIETARY_11N_RATES)
+#define WL_RATESET_SZ_HT_MCS WL_RATESET_SZ_VHT_MCS
+#else
+#define WL_RATESET_SZ_HT_MCS 8
+#endif
+
+#define WL_RATESET_SZ_HT_IOCTL 8
+
+#define WL_TX_CHAINS_MAX 4
+
+#define WL_RATE_DISABLED (-128)
+
+typedef enum wl_tx_bw {
+ WL_TX_BW_20,
+ WL_TX_BW_40,
+ WL_TX_BW_80,
+ WL_TX_BW_20IN40,
+ WL_TX_BW_20IN80,
+ WL_TX_BW_40IN80,
+ WL_TX_BW_160,
+ WL_TX_BW_20IN160,
+ WL_TX_BW_40IN160,
+ WL_TX_BW_80IN160,
+ WL_TX_BW_ALL,
+ WL_TX_BW_8080,
+ WL_TX_BW_8080CHAN2,
+ WL_TX_BW_20IN8080,
+ WL_TX_BW_40IN8080,
+ WL_TX_BW_80IN8080,
+ WL_TX_BW_2P5,
+ WL_TX_BW_5,
+ WL_TX_BW_10
+} wl_tx_bw_t;
+
+typedef enum wl_tx_mode {
+ WL_TX_MODE_NONE,
+ WL_TX_MODE_STBC,
+ WL_TX_MODE_CDD,
+ WL_TX_MODE_TXBF,
+ WL_NUM_TX_MODES
+} wl_tx_mode_t;
+
+typedef enum wl_tx_chains {
+ WL_TX_CHAINS_1 = 1,
+ WL_TX_CHAINS_2,
+ WL_TX_CHAINS_3,
+ WL_TX_CHAINS_4
+} wl_tx_chains_t;
+
+typedef enum wl_tx_nss {
+ WL_TX_NSS_1 = 1,
+ WL_TX_NSS_2,
+ WL_TX_NSS_3,
+ WL_TX_NSS_4
+} wl_tx_nss_t;
+
+typedef enum clm_rates {
+
+ WL_RATE_1X1_DSSS_1 = 0,
+ WL_RATE_1X1_DSSS_2 = 1,
+ WL_RATE_1X1_DSSS_5_5 = 2,
+ WL_RATE_1X1_DSSS_11 = 3,
+
+ WL_RATE_1X1_OFDM_6 = 4,
+ WL_RATE_1X1_OFDM_9 = 5,
+ WL_RATE_1X1_OFDM_12 = 6,
+ WL_RATE_1X1_OFDM_18 = 7,
+ WL_RATE_1X1_OFDM_24 = 8,
+ WL_RATE_1X1_OFDM_36 = 9,
+ WL_RATE_1X1_OFDM_48 = 10,
+ WL_RATE_1X1_OFDM_54 = 11,
+
+ WL_RATE_1X1_MCS0 = 12,
+ WL_RATE_1X1_MCS1 = 13,
+ WL_RATE_1X1_MCS2 = 14,
+ WL_RATE_1X1_MCS3 = 15,
+ WL_RATE_1X1_MCS4 = 16,
+ WL_RATE_1X1_MCS5 = 17,
+ WL_RATE_1X1_MCS6 = 18,
+ WL_RATE_1X1_MCS7 = 19,
+ WL_RATE_P_1X1_MCS87 = 20,
+ WL_RATE_P_1X1_MCS88 = 21,
+
+ WL_RATE_1X1_VHT0SS1 = 12,
+ WL_RATE_1X1_VHT1SS1 = 13,
+ WL_RATE_1X1_VHT2SS1 = 14,
+ WL_RATE_1X1_VHT3SS1 = 15,
+ WL_RATE_1X1_VHT4SS1 = 16,
+ WL_RATE_1X1_VHT5SS1 = 17,
+ WL_RATE_1X1_VHT6SS1 = 18,
+ WL_RATE_1X1_VHT7SS1 = 19,
+ WL_RATE_1X1_VHT8SS1 = 20,
+ WL_RATE_1X1_VHT9SS1 = 21,
+ WL_RATE_P_1X1_VHT10SS1 = 22,
+ WL_RATE_P_1X1_VHT11SS1 = 23,
+
+ WL_RATE_1X2_DSSS_1 = 24,
+ WL_RATE_1X2_DSSS_2 = 25,
+ WL_RATE_1X2_DSSS_5_5 = 26,
+ WL_RATE_1X2_DSSS_11 = 27,
+
+ WL_RATE_1X2_CDD_OFDM_6 = 28,
+ WL_RATE_1X2_CDD_OFDM_9 = 29,
+ WL_RATE_1X2_CDD_OFDM_12 = 30,
+ WL_RATE_1X2_CDD_OFDM_18 = 31,
+ WL_RATE_1X2_CDD_OFDM_24 = 32,
+ WL_RATE_1X2_CDD_OFDM_36 = 33,
+ WL_RATE_1X2_CDD_OFDM_48 = 34,
+ WL_RATE_1X2_CDD_OFDM_54 = 35,
+
+ WL_RATE_1X2_CDD_MCS0 = 36,
+ WL_RATE_1X2_CDD_MCS1 = 37,
+ WL_RATE_1X2_CDD_MCS2 = 38,
+ WL_RATE_1X2_CDD_MCS3 = 39,
+ WL_RATE_1X2_CDD_MCS4 = 40,
+ WL_RATE_1X2_CDD_MCS5 = 41,
+ WL_RATE_1X2_CDD_MCS6 = 42,
+ WL_RATE_1X2_CDD_MCS7 = 43,
+ WL_RATE_P_1X2_CDD_MCS87 = 44,
+ WL_RATE_P_1X2_CDD_MCS88 = 45,
+
+ WL_RATE_1X2_VHT0SS1 = 36,
+ WL_RATE_1X2_VHT1SS1 = 37,
+ WL_RATE_1X2_VHT2SS1 = 38,
+ WL_RATE_1X2_VHT3SS1 = 39,
+ WL_RATE_1X2_VHT4SS1 = 40,
+ WL_RATE_1X2_VHT5SS1 = 41,
+ WL_RATE_1X2_VHT6SS1 = 42,
+ WL_RATE_1X2_VHT7SS1 = 43,
+ WL_RATE_1X2_VHT8SS1 = 44,
+ WL_RATE_1X2_VHT9SS1 = 45,
+ WL_RATE_P_1X2_VHT10SS1 = 46,
+ WL_RATE_P_1X2_VHT11SS1 = 47,
+
+ WL_RATE_2X2_STBC_MCS0 = 48,
+ WL_RATE_2X2_STBC_MCS1 = 49,
+ WL_RATE_2X2_STBC_MCS2 = 50,
+ WL_RATE_2X2_STBC_MCS3 = 51,
+ WL_RATE_2X2_STBC_MCS4 = 52,
+ WL_RATE_2X2_STBC_MCS5 = 53,
+ WL_RATE_2X2_STBC_MCS6 = 54,
+ WL_RATE_2X2_STBC_MCS7 = 55,
+ WL_RATE_P_2X2_STBC_MCS87 = 56,
+ WL_RATE_P_2X2_STBC_MCS88 = 57,
+
+ WL_RATE_2X2_STBC_VHT0SS1 = 48,
+ WL_RATE_2X2_STBC_VHT1SS1 = 49,
+ WL_RATE_2X2_STBC_VHT2SS1 = 50,
+ WL_RATE_2X2_STBC_VHT3SS1 = 51,
+ WL_RATE_2X2_STBC_VHT4SS1 = 52,
+ WL_RATE_2X2_STBC_VHT5SS1 = 53,
+ WL_RATE_2X2_STBC_VHT6SS1 = 54,
+ WL_RATE_2X2_STBC_VHT7SS1 = 55,
+ WL_RATE_2X2_STBC_VHT8SS1 = 56,
+ WL_RATE_2X2_STBC_VHT9SS1 = 57,
+ WL_RATE_P_2X2_STBC_VHT10SS1 = 58,
+ WL_RATE_P_2X2_STBC_VHT11SS1 = 59,
+
+ WL_RATE_2X2_SDM_MCS8 = 60,
+ WL_RATE_2X2_SDM_MCS9 = 61,
+ WL_RATE_2X2_SDM_MCS10 = 62,
+ WL_RATE_2X2_SDM_MCS11 = 63,
+ WL_RATE_2X2_SDM_MCS12 = 64,
+ WL_RATE_2X2_SDM_MCS13 = 65,
+ WL_RATE_2X2_SDM_MCS14 = 66,
+ WL_RATE_2X2_SDM_MCS15 = 67,
+ WL_RATE_P_2X2_SDM_MCS99 = 68,
+ WL_RATE_P_2X2_SDM_MCS100 = 69,
+
+ WL_RATE_2X2_VHT0SS2 = 60,
+ WL_RATE_2X2_VHT1SS2 = 61,
+ WL_RATE_2X2_VHT2SS2 = 62,
+ WL_RATE_2X2_VHT3SS2 = 63,
+ WL_RATE_2X2_VHT4SS2 = 64,
+ WL_RATE_2X2_VHT5SS2 = 65,
+ WL_RATE_2X2_VHT6SS2 = 66,
+ WL_RATE_2X2_VHT7SS2 = 67,
+ WL_RATE_2X2_VHT8SS2 = 68,
+ WL_RATE_2X2_VHT9SS2 = 69,
+ WL_RATE_P_2X2_VHT10SS2 = 70,
+ WL_RATE_P_2X2_VHT11SS2 = 71,
+
+ WL_RATE_1X2_TXBF_OFDM_6 = 72,
+ WL_RATE_1X2_TXBF_OFDM_9 = 73,
+ WL_RATE_1X2_TXBF_OFDM_12 = 74,
+ WL_RATE_1X2_TXBF_OFDM_18 = 75,
+ WL_RATE_1X2_TXBF_OFDM_24 = 76,
+ WL_RATE_1X2_TXBF_OFDM_36 = 77,
+ WL_RATE_1X2_TXBF_OFDM_48 = 78,
+ WL_RATE_1X2_TXBF_OFDM_54 = 79,
+
+ WL_RATE_1X2_TXBF_MCS0 = 80,
+ WL_RATE_1X2_TXBF_MCS1 = 81,
+ WL_RATE_1X2_TXBF_MCS2 = 82,
+ WL_RATE_1X2_TXBF_MCS3 = 83,
+ WL_RATE_1X2_TXBF_MCS4 = 84,
+ WL_RATE_1X2_TXBF_MCS5 = 85,
+ WL_RATE_1X2_TXBF_MCS6 = 86,
+ WL_RATE_1X2_TXBF_MCS7 = 87,
+ WL_RATE_P_1X2_TXBF_MCS87 = 88,
+ WL_RATE_P_1X2_TXBF_MCS88 = 89,
+
+ WL_RATE_1X2_TXBF_VHT0SS1 = 80,
+ WL_RATE_1X2_TXBF_VHT1SS1 = 81,
+ WL_RATE_1X2_TXBF_VHT2SS1 = 82,
+ WL_RATE_1X2_TXBF_VHT3SS1 = 83,
+ WL_RATE_1X2_TXBF_VHT4SS1 = 84,
+ WL_RATE_1X2_TXBF_VHT5SS1 = 85,
+ WL_RATE_1X2_TXBF_VHT6SS1 = 86,
+ WL_RATE_1X2_TXBF_VHT7SS1 = 87,
+ WL_RATE_1X2_TXBF_VHT8SS1 = 88,
+ WL_RATE_1X2_TXBF_VHT9SS1 = 89,
+ WL_RATE_P_1X2_TXBF_VHT10SS1 = 90,
+ WL_RATE_P_1X2_TXBF_VHT11SS1 = 91,
+
+ WL_RATE_2X2_TXBF_SDM_MCS8 = 92,
+ WL_RATE_2X2_TXBF_SDM_MCS9 = 93,
+ WL_RATE_2X2_TXBF_SDM_MCS10 = 94,
+ WL_RATE_2X2_TXBF_SDM_MCS11 = 95,
+ WL_RATE_2X2_TXBF_SDM_MCS12 = 96,
+ WL_RATE_2X2_TXBF_SDM_MCS13 = 97,
+ WL_RATE_2X2_TXBF_SDM_MCS14 = 98,
+ WL_RATE_2X2_TXBF_SDM_MCS15 = 99,
+ WL_RATE_P_2X2_TXBF_SDM_MCS99 = 100,
+ WL_RATE_P_2X2_TXBF_SDM_MCS100 = 101,
+
+ WL_RATE_2X2_TXBF_VHT0SS2 = 92,
+ WL_RATE_2X2_TXBF_VHT1SS2 = 93,
+ WL_RATE_2X2_TXBF_VHT2SS2 = 94,
+ WL_RATE_2X2_TXBF_VHT3SS2 = 95,
+ WL_RATE_2X2_TXBF_VHT4SS2 = 96,
+ WL_RATE_2X2_TXBF_VHT5SS2 = 97,
+ WL_RATE_2X2_TXBF_VHT6SS2 = 98,
+ WL_RATE_2X2_TXBF_VHT7SS2 = 99,
+ WL_RATE_2X2_TXBF_VHT8SS2 = 100,
+ WL_RATE_2X2_TXBF_VHT9SS2 = 101,
+ WL_RATE_P_2X2_TXBF_VHT10SS2 = 102,
+ WL_RATE_P_2X2_TXBF_VHT11SS2 = 103,
+
+ WL_RATE_1X3_DSSS_1 = 104,
+ WL_RATE_1X3_DSSS_2 = 105,
+ WL_RATE_1X3_DSSS_5_5 = 106,
+ WL_RATE_1X3_DSSS_11 = 107,
+
+ WL_RATE_1X3_CDD_OFDM_6 = 108,
+ WL_RATE_1X3_CDD_OFDM_9 = 109,
+ WL_RATE_1X3_CDD_OFDM_12 = 110,
+ WL_RATE_1X3_CDD_OFDM_18 = 111,
+ WL_RATE_1X3_CDD_OFDM_24 = 112,
+ WL_RATE_1X3_CDD_OFDM_36 = 113,
+ WL_RATE_1X3_CDD_OFDM_48 = 114,
+ WL_RATE_1X3_CDD_OFDM_54 = 115,
+
+ WL_RATE_1X3_CDD_MCS0 = 116,
+ WL_RATE_1X3_CDD_MCS1 = 117,
+ WL_RATE_1X3_CDD_MCS2 = 118,
+ WL_RATE_1X3_CDD_MCS3 = 119,
+ WL_RATE_1X3_CDD_MCS4 = 120,
+ WL_RATE_1X3_CDD_MCS5 = 121,
+ WL_RATE_1X3_CDD_MCS6 = 122,
+ WL_RATE_1X3_CDD_MCS7 = 123,
+ WL_RATE_P_1X3_CDD_MCS87 = 124,
+ WL_RATE_P_1X3_CDD_MCS88 = 125,
+
+ WL_RATE_1X3_VHT0SS1 = 116,
+ WL_RATE_1X3_VHT1SS1 = 117,
+ WL_RATE_1X3_VHT2SS1 = 118,
+ WL_RATE_1X3_VHT3SS1 = 119,
+ WL_RATE_1X3_VHT4SS1 = 120,
+ WL_RATE_1X3_VHT5SS1 = 121,
+ WL_RATE_1X3_VHT6SS1 = 122,
+ WL_RATE_1X3_VHT7SS1 = 123,
+ WL_RATE_1X3_VHT8SS1 = 124,
+ WL_RATE_1X3_VHT9SS1 = 125,
+ WL_RATE_P_1X3_VHT10SS1 = 126,
+ WL_RATE_P_1X3_VHT11SS1 = 127,
+
+ WL_RATE_2X3_STBC_MCS0 = 128,
+ WL_RATE_2X3_STBC_MCS1 = 129,
+ WL_RATE_2X3_STBC_MCS2 = 130,
+ WL_RATE_2X3_STBC_MCS3 = 131,
+ WL_RATE_2X3_STBC_MCS4 = 132,
+ WL_RATE_2X3_STBC_MCS5 = 133,
+ WL_RATE_2X3_STBC_MCS6 = 134,
+ WL_RATE_2X3_STBC_MCS7 = 135,
+ WL_RATE_P_2X3_STBC_MCS87 = 136,
+ WL_RATE_P_2X3_STBC_MCS88 = 137,
+
+ WL_RATE_2X3_STBC_VHT0SS1 = 128,
+ WL_RATE_2X3_STBC_VHT1SS1 = 129,
+ WL_RATE_2X3_STBC_VHT2SS1 = 130,
+ WL_RATE_2X3_STBC_VHT3SS1 = 131,
+ WL_RATE_2X3_STBC_VHT4SS1 = 132,
+ WL_RATE_2X3_STBC_VHT5SS1 = 133,
+ WL_RATE_2X3_STBC_VHT6SS1 = 134,
+ WL_RATE_2X3_STBC_VHT7SS1 = 135,
+ WL_RATE_2X3_STBC_VHT8SS1 = 136,
+ WL_RATE_2X3_STBC_VHT9SS1 = 137,
+ WL_RATE_P_2X3_STBC_VHT10SS1 = 138,
+ WL_RATE_P_2X3_STBC_VHT11SS1 = 139,
+
+ WL_RATE_2X3_SDM_MCS8 = 140,
+ WL_RATE_2X3_SDM_MCS9 = 141,
+ WL_RATE_2X3_SDM_MCS10 = 142,
+ WL_RATE_2X3_SDM_MCS11 = 143,
+ WL_RATE_2X3_SDM_MCS12 = 144,
+ WL_RATE_2X3_SDM_MCS13 = 145,
+ WL_RATE_2X3_SDM_MCS14 = 146,
+ WL_RATE_2X3_SDM_MCS15 = 147,
+ WL_RATE_P_2X3_SDM_MCS99 = 148,
+ WL_RATE_P_2X3_SDM_MCS100 = 149,
+
+ WL_RATE_2X3_VHT0SS2 = 140,
+ WL_RATE_2X3_VHT1SS2 = 141,
+ WL_RATE_2X3_VHT2SS2 = 142,
+ WL_RATE_2X3_VHT3SS2 = 143,
+ WL_RATE_2X3_VHT4SS2 = 144,
+ WL_RATE_2X3_VHT5SS2 = 145,
+ WL_RATE_2X3_VHT6SS2 = 146,
+ WL_RATE_2X3_VHT7SS2 = 147,
+ WL_RATE_2X3_VHT8SS2 = 148,
+ WL_RATE_2X3_VHT9SS2 = 149,
+ WL_RATE_P_2X3_VHT10SS2 = 150,
+ WL_RATE_P_2X3_VHT11SS2 = 151,
+
+ WL_RATE_3X3_SDM_MCS16 = 152,
+ WL_RATE_3X3_SDM_MCS17 = 153,
+ WL_RATE_3X3_SDM_MCS18 = 154,
+ WL_RATE_3X3_SDM_MCS19 = 155,
+ WL_RATE_3X3_SDM_MCS20 = 156,
+ WL_RATE_3X3_SDM_MCS21 = 157,
+ WL_RATE_3X3_SDM_MCS22 = 158,
+ WL_RATE_3X3_SDM_MCS23 = 159,
+ WL_RATE_P_3X3_SDM_MCS101 = 160,
+ WL_RATE_P_3X3_SDM_MCS102 = 161,
+
+ WL_RATE_3X3_VHT0SS3 = 152,
+ WL_RATE_3X3_VHT1SS3 = 153,
+ WL_RATE_3X3_VHT2SS3 = 154,
+ WL_RATE_3X3_VHT3SS3 = 155,
+ WL_RATE_3X3_VHT4SS3 = 156,
+ WL_RATE_3X3_VHT5SS3 = 157,
+ WL_RATE_3X3_VHT6SS3 = 158,
+ WL_RATE_3X3_VHT7SS3 = 159,
+ WL_RATE_3X3_VHT8SS3 = 160,
+ WL_RATE_3X3_VHT9SS3 = 161,
+ WL_RATE_P_3X3_VHT10SS3 = 162,
+ WL_RATE_P_3X3_VHT11SS3 = 163,
+
+ WL_RATE_1X3_TXBF_OFDM_6 = 164,
+ WL_RATE_1X3_TXBF_OFDM_9 = 165,
+ WL_RATE_1X3_TXBF_OFDM_12 = 166,
+ WL_RATE_1X3_TXBF_OFDM_18 = 167,
+ WL_RATE_1X3_TXBF_OFDM_24 = 168,
+ WL_RATE_1X3_TXBF_OFDM_36 = 169,
+ WL_RATE_1X3_TXBF_OFDM_48 = 170,
+ WL_RATE_1X3_TXBF_OFDM_54 = 171,
+
+ WL_RATE_1X3_TXBF_MCS0 = 172,
+ WL_RATE_1X3_TXBF_MCS1 = 173,
+ WL_RATE_1X3_TXBF_MCS2 = 174,
+ WL_RATE_1X3_TXBF_MCS3 = 175,
+ WL_RATE_1X3_TXBF_MCS4 = 176,
+ WL_RATE_1X3_TXBF_MCS5 = 177,
+ WL_RATE_1X3_TXBF_MCS6 = 178,
+ WL_RATE_1X3_TXBF_MCS7 = 179,
+ WL_RATE_P_1X3_TXBF_MCS87 = 180,
+ WL_RATE_P_1X3_TXBF_MCS88 = 181,
+
+ WL_RATE_1X3_TXBF_VHT0SS1 = 172,
+ WL_RATE_1X3_TXBF_VHT1SS1 = 173,
+ WL_RATE_1X3_TXBF_VHT2SS1 = 174,
+ WL_RATE_1X3_TXBF_VHT3SS1 = 175,
+ WL_RATE_1X3_TXBF_VHT4SS1 = 176,
+ WL_RATE_1X3_TXBF_VHT5SS1 = 177,
+ WL_RATE_1X3_TXBF_VHT6SS1 = 178,
+ WL_RATE_1X3_TXBF_VHT7SS1 = 179,
+ WL_RATE_1X3_TXBF_VHT8SS1 = 180,
+ WL_RATE_1X3_TXBF_VHT9SS1 = 181,
+ WL_RATE_P_1X3_TXBF_VHT10SS1 = 182,
+ WL_RATE_P_1X3_TXBF_VHT11SS1 = 183,
+
+ WL_RATE_2X3_TXBF_SDM_MCS8 = 184,
+ WL_RATE_2X3_TXBF_SDM_MCS9 = 185,
+ WL_RATE_2X3_TXBF_SDM_MCS10 = 186,
+ WL_RATE_2X3_TXBF_SDM_MCS11 = 187,
+ WL_RATE_2X3_TXBF_SDM_MCS12 = 188,
+ WL_RATE_2X3_TXBF_SDM_MCS13 = 189,
+ WL_RATE_2X3_TXBF_SDM_MCS14 = 190,
+ WL_RATE_2X3_TXBF_SDM_MCS15 = 191,
+ WL_RATE_P_2X3_TXBF_SDM_MCS99 = 192,
+ WL_RATE_P_2X3_TXBF_SDM_MCS100 = 193,
+
+ WL_RATE_2X3_TXBF_VHT0SS2 = 184,
+ WL_RATE_2X3_TXBF_VHT1SS2 = 185,
+ WL_RATE_2X3_TXBF_VHT2SS2 = 186,
+ WL_RATE_2X3_TXBF_VHT3SS2 = 187,
+ WL_RATE_2X3_TXBF_VHT4SS2 = 188,
+ WL_RATE_2X3_TXBF_VHT5SS2 = 189,
+ WL_RATE_2X3_TXBF_VHT6SS2 = 190,
+ WL_RATE_2X3_TXBF_VHT7SS2 = 191,
+ WL_RATE_2X3_TXBF_VHT8SS2 = 192,
+ WL_RATE_2X3_TXBF_VHT9SS2 = 193,
+ WL_RATE_P_2X3_TXBF_VHT10SS2 = 194,
+ WL_RATE_P_2X3_TXBF_VHT11SS2 = 195,
+
+ WL_RATE_3X3_TXBF_SDM_MCS16 = 196,
+ WL_RATE_3X3_TXBF_SDM_MCS17 = 197,
+ WL_RATE_3X3_TXBF_SDM_MCS18 = 198,
+ WL_RATE_3X3_TXBF_SDM_MCS19 = 199,
+ WL_RATE_3X3_TXBF_SDM_MCS20 = 200,
+ WL_RATE_3X3_TXBF_SDM_MCS21 = 201,
+ WL_RATE_3X3_TXBF_SDM_MCS22 = 202,
+ WL_RATE_3X3_TXBF_SDM_MCS23 = 203,
+ WL_RATE_P_3X3_TXBF_SDM_MCS101 = 204,
+ WL_RATE_P_3X3_TXBF_SDM_MCS102 = 205,
+
+ WL_RATE_3X3_TXBF_VHT0SS3 = 196,
+ WL_RATE_3X3_TXBF_VHT1SS3 = 197,
+ WL_RATE_3X3_TXBF_VHT2SS3 = 198,
+ WL_RATE_3X3_TXBF_VHT3SS3 = 199,
+ WL_RATE_3X3_TXBF_VHT4SS3 = 200,
+ WL_RATE_3X3_TXBF_VHT5SS3 = 201,
+ WL_RATE_3X3_TXBF_VHT6SS3 = 202,
+ WL_RATE_3X3_TXBF_VHT7SS3 = 203,
+ WL_RATE_3X3_TXBF_VHT8SS3 = 204,
+ WL_RATE_3X3_TXBF_VHT9SS3 = 205,
+ WL_RATE_P_3X3_TXBF_VHT10SS3 = 206,
+ WL_RATE_P_3X3_TXBF_VHT11SS3 = 207,
+
+ WL_RATE_1X4_DSSS_1 = 208,
+ WL_RATE_1X4_DSSS_2 = 209,
+ WL_RATE_1X4_DSSS_5_5 = 210,
+ WL_RATE_1X4_DSSS_11 = 211,
+
+ WL_RATE_1X4_CDD_OFDM_6 = 212,
+ WL_RATE_1X4_CDD_OFDM_9 = 213,
+ WL_RATE_1X4_CDD_OFDM_12 = 214,
+ WL_RATE_1X4_CDD_OFDM_18 = 215,
+ WL_RATE_1X4_CDD_OFDM_24 = 216,
+ WL_RATE_1X4_CDD_OFDM_36 = 217,
+ WL_RATE_1X4_CDD_OFDM_48 = 218,
+ WL_RATE_1X4_CDD_OFDM_54 = 219,
+
+ WL_RATE_1X4_CDD_MCS0 = 220,
+ WL_RATE_1X4_CDD_MCS1 = 221,
+ WL_RATE_1X4_CDD_MCS2 = 222,
+ WL_RATE_1X4_CDD_MCS3 = 223,
+ WL_RATE_1X4_CDD_MCS4 = 224,
+ WL_RATE_1X4_CDD_MCS5 = 225,
+ WL_RATE_1X4_CDD_MCS6 = 226,
+ WL_RATE_1X4_CDD_MCS7 = 227,
+ WL_RATE_P_1X4_CDD_MCS87 = 228,
+ WL_RATE_P_1X4_CDD_MCS88 = 229,
+
+ WL_RATE_1X4_VHT0SS1 = 220,
+ WL_RATE_1X4_VHT1SS1 = 221,
+ WL_RATE_1X4_VHT2SS1 = 222,
+ WL_RATE_1X4_VHT3SS1 = 223,
+ WL_RATE_1X4_VHT4SS1 = 224,
+ WL_RATE_1X4_VHT5SS1 = 225,
+ WL_RATE_1X4_VHT6SS1 = 226,
+ WL_RATE_1X4_VHT7SS1 = 227,
+ WL_RATE_1X4_VHT8SS1 = 228,
+ WL_RATE_1X4_VHT9SS1 = 229,
+ WL_RATE_P_1X4_VHT10SS1 = 230,
+ WL_RATE_P_1X4_VHT11SS1 = 231,
+
+ WL_RATE_2X4_STBC_MCS0 = 232,
+ WL_RATE_2X4_STBC_MCS1 = 233,
+ WL_RATE_2X4_STBC_MCS2 = 234,
+ WL_RATE_2X4_STBC_MCS3 = 235,
+ WL_RATE_2X4_STBC_MCS4 = 236,
+ WL_RATE_2X4_STBC_MCS5 = 237,
+ WL_RATE_2X4_STBC_MCS6 = 238,
+ WL_RATE_2X4_STBC_MCS7 = 239,
+ WL_RATE_P_2X4_STBC_MCS87 = 240,
+ WL_RATE_P_2X4_STBC_MCS88 = 241,
+
+ WL_RATE_2X4_STBC_VHT0SS1 = 232,
+ WL_RATE_2X4_STBC_VHT1SS1 = 233,
+ WL_RATE_2X4_STBC_VHT2SS1 = 234,
+ WL_RATE_2X4_STBC_VHT3SS1 = 235,
+ WL_RATE_2X4_STBC_VHT4SS1 = 236,
+ WL_RATE_2X4_STBC_VHT5SS1 = 237,
+ WL_RATE_2X4_STBC_VHT6SS1 = 238,
+ WL_RATE_2X4_STBC_VHT7SS1 = 239,
+ WL_RATE_2X4_STBC_VHT8SS1 = 240,
+ WL_RATE_2X4_STBC_VHT9SS1 = 241,
+ WL_RATE_P_2X4_STBC_VHT10SS1 = 242,
+ WL_RATE_P_2X4_STBC_VHT11SS1 = 243,
+
+ WL_RATE_2X4_SDM_MCS8 = 244,
+ WL_RATE_2X4_SDM_MCS9 = 245,
+ WL_RATE_2X4_SDM_MCS10 = 246,
+ WL_RATE_2X4_SDM_MCS11 = 247,
+ WL_RATE_2X4_SDM_MCS12 = 248,
+ WL_RATE_2X4_SDM_MCS13 = 249,
+ WL_RATE_2X4_SDM_MCS14 = 250,
+ WL_RATE_2X4_SDM_MCS15 = 251,
+ WL_RATE_P_2X4_SDM_MCS99 = 252,
+ WL_RATE_P_2X4_SDM_MCS100 = 253,
+
+ WL_RATE_2X4_VHT0SS2 = 244,
+ WL_RATE_2X4_VHT1SS2 = 245,
+ WL_RATE_2X4_VHT2SS2 = 246,
+ WL_RATE_2X4_VHT3SS2 = 247,
+ WL_RATE_2X4_VHT4SS2 = 248,
+ WL_RATE_2X4_VHT5SS2 = 249,
+ WL_RATE_2X4_VHT6SS2 = 250,
+ WL_RATE_2X4_VHT7SS2 = 251,
+ WL_RATE_2X4_VHT8SS2 = 252,
+ WL_RATE_2X4_VHT9SS2 = 253,
+ WL_RATE_P_2X4_VHT10SS2 = 254,
+ WL_RATE_P_2X4_VHT11SS2 = 255,
+
+ WL_RATE_3X4_SDM_MCS16 = 256,
+ WL_RATE_3X4_SDM_MCS17 = 257,
+ WL_RATE_3X4_SDM_MCS18 = 258,
+ WL_RATE_3X4_SDM_MCS19 = 259,
+ WL_RATE_3X4_SDM_MCS20 = 260,
+ WL_RATE_3X4_SDM_MCS21 = 261,
+ WL_RATE_3X4_SDM_MCS22 = 262,
+ WL_RATE_3X4_SDM_MCS23 = 263,
+ WL_RATE_P_3X4_SDM_MCS101 = 264,
+ WL_RATE_P_3X4_SDM_MCS102 = 265,
+
+ WL_RATE_3X4_VHT0SS3 = 256,
+ WL_RATE_3X4_VHT1SS3 = 257,
+ WL_RATE_3X4_VHT2SS3 = 258,
+ WL_RATE_3X4_VHT3SS3 = 259,
+ WL_RATE_3X4_VHT4SS3 = 260,
+ WL_RATE_3X4_VHT5SS3 = 261,
+ WL_RATE_3X4_VHT6SS3 = 262,
+ WL_RATE_3X4_VHT7SS3 = 263,
+ WL_RATE_3X4_VHT8SS3 = 264,
+ WL_RATE_3X4_VHT9SS3 = 265,
+ WL_RATE_P_3X4_VHT10SS3 = 266,
+ WL_RATE_P_3X4_VHT11SS3 = 267,
+
+ WL_RATE_4X4_SDM_MCS24 = 268,
+ WL_RATE_4X4_SDM_MCS25 = 269,
+ WL_RATE_4X4_SDM_MCS26 = 270,
+ WL_RATE_4X4_SDM_MCS27 = 271,
+ WL_RATE_4X4_SDM_MCS28 = 272,
+ WL_RATE_4X4_SDM_MCS29 = 273,
+ WL_RATE_4X4_SDM_MCS30 = 274,
+ WL_RATE_4X4_SDM_MCS31 = 275,
+ WL_RATE_P_4X4_SDM_MCS103 = 276,
+ WL_RATE_P_4X4_SDM_MCS104 = 277,
+
+ WL_RATE_4X4_VHT0SS4 = 268,
+ WL_RATE_4X4_VHT1SS4 = 269,
+ WL_RATE_4X4_VHT2SS4 = 270,
+ WL_RATE_4X4_VHT3SS4 = 271,
+ WL_RATE_4X4_VHT4SS4 = 272,
+ WL_RATE_4X4_VHT5SS4 = 273,
+ WL_RATE_4X4_VHT6SS4 = 274,
+ WL_RATE_4X4_VHT7SS4 = 275,
+ WL_RATE_4X4_VHT8SS4 = 276,
+ WL_RATE_4X4_VHT9SS4 = 277,
+ WL_RATE_P_4X4_VHT10SS4 = 278,
+ WL_RATE_P_4X4_VHT11SS4 = 279,
+
+ WL_RATE_1X4_TXBF_OFDM_6 = 280,
+ WL_RATE_1X4_TXBF_OFDM_9 = 281,
+ WL_RATE_1X4_TXBF_OFDM_12 = 282,
+ WL_RATE_1X4_TXBF_OFDM_18 = 283,
+ WL_RATE_1X4_TXBF_OFDM_24 = 284,
+ WL_RATE_1X4_TXBF_OFDM_36 = 285,
+ WL_RATE_1X4_TXBF_OFDM_48 = 286,
+ WL_RATE_1X4_TXBF_OFDM_54 = 287,
+
+ WL_RATE_1X4_TXBF_MCS0 = 288,
+ WL_RATE_1X4_TXBF_MCS1 = 289,
+ WL_RATE_1X4_TXBF_MCS2 = 290,
+ WL_RATE_1X4_TXBF_MCS3 = 291,
+ WL_RATE_1X4_TXBF_MCS4 = 292,
+ WL_RATE_1X4_TXBF_MCS5 = 293,
+ WL_RATE_1X4_TXBF_MCS6 = 294,
+ WL_RATE_1X4_TXBF_MCS7 = 295,
+ WL_RATE_P_1X4_TXBF_MCS87 = 296,
+ WL_RATE_P_1X4_TXBF_MCS88 = 297,
+
+ WL_RATE_1X4_TXBF_VHT0SS1 = 288,
+ WL_RATE_1X4_TXBF_VHT1SS1 = 289,
+ WL_RATE_1X4_TXBF_VHT2SS1 = 290,
+ WL_RATE_1X4_TXBF_VHT3SS1 = 291,
+ WL_RATE_1X4_TXBF_VHT4SS1 = 292,
+ WL_RATE_1X4_TXBF_VHT5SS1 = 293,
+ WL_RATE_1X4_TXBF_VHT6SS1 = 294,
+ WL_RATE_1X4_TXBF_VHT7SS1 = 295,
+ WL_RATE_1X4_TXBF_VHT8SS1 = 296,
+ WL_RATE_1X4_TXBF_VHT9SS1 = 297,
+ WL_RATE_P_1X4_TXBF_VHT10SS1 = 298,
+ WL_RATE_P_1X4_TXBF_VHT11SS1 = 299,
+
+ WL_RATE_2X4_TXBF_SDM_MCS8 = 300,
+ WL_RATE_2X4_TXBF_SDM_MCS9 = 301,
+ WL_RATE_2X4_TXBF_SDM_MCS10 = 302,
+ WL_RATE_2X4_TXBF_SDM_MCS11 = 303,
+ WL_RATE_2X4_TXBF_SDM_MCS12 = 304,
+ WL_RATE_2X4_TXBF_SDM_MCS13 = 305,
+ WL_RATE_2X4_TXBF_SDM_MCS14 = 306,
+ WL_RATE_2X4_TXBF_SDM_MCS15 = 307,
+ WL_RATE_P_2X4_TXBF_SDM_MCS99 = 308,
+ WL_RATE_P_2X4_TXBF_SDM_MCS100 = 309,
+
+ WL_RATE_2X4_TXBF_VHT0SS2 = 300,
+ WL_RATE_2X4_TXBF_VHT1SS2 = 301,
+ WL_RATE_2X4_TXBF_VHT2SS2 = 302,
+ WL_RATE_2X4_TXBF_VHT3SS2 = 303,
+ WL_RATE_2X4_TXBF_VHT4SS2 = 304,
+ WL_RATE_2X4_TXBF_VHT5SS2 = 305,
+ WL_RATE_2X4_TXBF_VHT6SS2 = 306,
+ WL_RATE_2X4_TXBF_VHT7SS2 = 307,
+ WL_RATE_2X4_TXBF_VHT8SS2 = 308,
+ WL_RATE_2X4_TXBF_VHT9SS2 = 309,
+ WL_RATE_P_2X4_TXBF_VHT10SS2 = 310,
+ WL_RATE_P_2X4_TXBF_VHT11SS2 = 311,
+
+ WL_RATE_3X4_TXBF_SDM_MCS16 = 312,
+ WL_RATE_3X4_TXBF_SDM_MCS17 = 313,
+ WL_RATE_3X4_TXBF_SDM_MCS18 = 314,
+ WL_RATE_3X4_TXBF_SDM_MCS19 = 315,
+ WL_RATE_3X4_TXBF_SDM_MCS20 = 316,
+ WL_RATE_3X4_TXBF_SDM_MCS21 = 317,
+ WL_RATE_3X4_TXBF_SDM_MCS22 = 318,
+ WL_RATE_3X4_TXBF_SDM_MCS23 = 319,
+ WL_RATE_P_3X4_TXBF_SDM_MCS101 = 320,
+ WL_RATE_P_3X4_TXBF_SDM_MCS102 = 321,
+
+ WL_RATE_3X4_TXBF_VHT0SS3 = 312,
+ WL_RATE_3X4_TXBF_VHT1SS3 = 313,
+ WL_RATE_3X4_TXBF_VHT2SS3 = 314,
+ WL_RATE_3X4_TXBF_VHT3SS3 = 315,
+ WL_RATE_3X4_TXBF_VHT4SS3 = 316,
+ WL_RATE_3X4_TXBF_VHT5SS3 = 317,
+ WL_RATE_3X4_TXBF_VHT6SS3 = 318,
+ WL_RATE_3X4_TXBF_VHT7SS3 = 319,
+ WL_RATE_P_3X4_TXBF_VHT8SS3 = 320,
+ WL_RATE_P_3X4_TXBF_VHT9SS3 = 321,
+ WL_RATE_P_3X4_TXBF_VHT10SS3 = 322,
+ WL_RATE_P_3X4_TXBF_VHT11SS3 = 323,
+
+ WL_RATE_4X4_TXBF_SDM_MCS24 = 324,
+ WL_RATE_4X4_TXBF_SDM_MCS25 = 325,
+ WL_RATE_4X4_TXBF_SDM_MCS26 = 326,
+ WL_RATE_4X4_TXBF_SDM_MCS27 = 327,
+ WL_RATE_4X4_TXBF_SDM_MCS28 = 328,
+ WL_RATE_4X4_TXBF_SDM_MCS29 = 329,
+ WL_RATE_4X4_TXBF_SDM_MCS30 = 330,
+ WL_RATE_4X4_TXBF_SDM_MCS31 = 331,
+ WL_RATE_P_4X4_TXBF_SDM_MCS103 = 332,
+ WL_RATE_P_4X4_TXBF_SDM_MCS104 = 333,
+
+ WL_RATE_4X4_TXBF_VHT0SS4 = 324,
+ WL_RATE_4X4_TXBF_VHT1SS4 = 325,
+ WL_RATE_4X4_TXBF_VHT2SS4 = 326,
+ WL_RATE_4X4_TXBF_VHT3SS4 = 327,
+ WL_RATE_4X4_TXBF_VHT4SS4 = 328,
+ WL_RATE_4X4_TXBF_VHT5SS4 = 329,
+ WL_RATE_4X4_TXBF_VHT6SS4 = 330,
+ WL_RATE_4X4_TXBF_VHT7SS4 = 331,
+ WL_RATE_P_4X4_TXBF_VHT8SS4 = 332,
+ WL_RATE_P_4X4_TXBF_VHT9SS4 = 333,
+ WL_RATE_P_4X4_TXBF_VHT10SS4 = 334,
+ WL_RATE_P_4X4_TXBF_VHT11SS4 = 335
+
+} clm_rates_t;
+
+#define WL_NUMRATES 336
+
+#endif
diff --git a/src/shared/linux_osl.c b/src/shared/linux_osl.c
new file mode 100644
index 0000000..6157d18
--- /dev/null
+++ b/src/shared/linux_osl.c
@@ -0,0 +1,1107 @@
+/*
+ * Linux OS Independent Layer
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: linux_osl.c 383331 2013-02-06 10:27:24Z $
+ */
+
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <linuxver.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <linux/delay.h>
+#include <pcicfg.h>
+
+#include <linux/fs.h>
+
+#define PCI_CFG_RETRY 10
+
+#define OS_HANDLE_MAGIC 0x1234abcd
+#define BCM_MEM_FILENAME_LEN 24
+
+typedef struct bcm_mem_link {
+ struct bcm_mem_link *prev;
+ struct bcm_mem_link *next;
+ uint size;
+ int line;
+ void *osh;
+ char file[BCM_MEM_FILENAME_LEN];
+} bcm_mem_link_t;
+
+struct osl_info {
+ osl_pubinfo_t pub;
+ uint magic;
+ void *pdev;
+ atomic_t malloced;
+ atomic_t pktalloced;
+ uint failed;
+ uint bustype;
+ bcm_mem_link_t *dbgmem_list;
+ spinlock_t dbgmem_lock;
+ spinlock_t pktalloc_lock;
+};
+
+#define OSL_PKTTAG_CLEAR(p) \
+do { \
+ struct sk_buff *s = (struct sk_buff *)(p); \
+ ASSERT(OSL_PKTTAG_SZ == 32); \
+ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \
+ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \
+ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \
+ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \
+} while (0)
+
+uint32 g_assert_type = FALSE;
+
+static int16 linuxbcmerrormap[] =
+{ 0,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -E2BIG,
+ -E2BIG,
+ -EBUSY,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EFAULT,
+ -ENOMEM,
+ -EOPNOTSUPP,
+ -EMSGSIZE,
+ -EINVAL,
+ -EPERM,
+ -ENOMEM,
+ -EINVAL,
+ -ERANGE,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EINVAL,
+ -EIO,
+ -ENODEV,
+ -EINVAL,
+ -EIO,
+ -EIO,
+ -ENODEV,
+ -EINVAL,
+ -ENODATA,
+ -EINVAL,
+
+#if BCME_LAST != -43
+#error "You need to add a OS error translation in the linuxbcmerrormap \
+ for new error code defined in bcmutils.h"
+#endif
+};
+
+int
+osl_error(int bcmerror)
+{
+ if (bcmerror > 0)
+ bcmerror = 0;
+ else if (bcmerror < BCME_LAST)
+ bcmerror = BCME_ERROR;
+
+ return linuxbcmerrormap[-bcmerror];
+}
+
+extern uint8* dhd_os_prealloc(void *osh, int section, int size);
+
+osl_t *
+osl_attach(void *pdev, uint bustype, bool pkttag)
+{
+ osl_t *osh;
+
+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
+ ASSERT(osh);
+
+ bzero(osh, sizeof(osl_t));
+
+ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
+
+ osh->magic = OS_HANDLE_MAGIC;
+ atomic_set(&osh->malloced, 0);
+ osh->failed = 0;
+ osh->dbgmem_list = NULL;
+ spin_lock_init(&(osh->dbgmem_lock));
+ osh->pdev = pdev;
+ osh->pub.pkttag = pkttag;
+ osh->bustype = bustype;
+
+ switch (bustype) {
+ case PCI_BUS:
+ case SI_BUS:
+ case PCMCIA_BUS:
+ osh->pub.mmbus = TRUE;
+ break;
+ case JTAG_BUS:
+ case SDIO_BUS:
+ case USB_BUS:
+ case SPI_BUS:
+ case RPC_BUS:
+ osh->pub.mmbus = FALSE;
+ break;
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ spin_lock_init(&(osh->pktalloc_lock));
+
+#ifdef BCMDBG
+ if (pkttag) {
+ struct sk_buff *skb;
+ BCM_REFERENCE(skb);
+ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
+ }
+#endif
+ return osh;
+}
+
+void
+osl_detach(osl_t *osh)
+{
+ if (osh == NULL)
+ return;
+
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ kfree(osh);
+}
+
+static struct sk_buff *osl_alloc_skb(unsigned int len)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+ gfp_t flags = GFP_ATOMIC;
+ struct sk_buff *skb;
+
+ skb = __dev_alloc_skb(len, flags);
+ return skb;
+#else
+ return dev_alloc_skb(len);
+#endif
+}
+
+struct sk_buff * BCMFASTPATH
+osl_pkt_tonative(osl_t *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+
+ }
+ return (struct sk_buff *)pkt;
+}
+
+void * BCMFASTPATH
+osl_pkt_frmnative(osl_t *osh, void *pkt)
+{
+ struct sk_buff *nskb;
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(pkt);
+
+ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) {
+ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced);
+
+ }
+ return (void *)pkt;
+}
+
+void * BCMFASTPATH
+osl_pktget(osl_t *osh, uint len)
+{
+ struct sk_buff *skb;
+
+ if ((skb = osl_alloc_skb(len))) {
+#ifdef BCMDBG
+ skb_put(skb, len);
+#else
+ skb->tail += len;
+ skb->len += len;
+#endif
+ skb->priority = 0;
+
+ atomic_inc(&osh->pktalloced);
+ }
+
+ return ((void*) skb);
+}
+
+void BCMFASTPATH
+osl_pktfree(osl_t *osh, void *p, bool send)
+{
+ struct sk_buff *skb, *nskb;
+
+ skb = (struct sk_buff*) p;
+
+ if (send && osh->pub.tx_fn)
+ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0);
+
+ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE);
+
+ while (skb) {
+ nskb = skb->next;
+ skb->next = NULL;
+
+ {
+ if (skb->destructor)
+
+ dev_kfree_skb_any(skb);
+ else
+
+ dev_kfree_skb(skb);
+ }
+ atomic_dec(&osh->pktalloced);
+ skb = nskb;
+ }
+}
+
+uint32
+osl_pci_read_config(osl_t *osh, uint offset, uint size)
+{
+ uint val = 0;
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ ASSERT(size == 4);
+
+ do {
+ pci_read_config_dword(osh->pdev, offset, &val);
+ if (val != 0xffffffff)
+ break;
+ } while (retry--);
+
+#ifdef BCMDBG
+ if (retry < PCI_CFG_RETRY)
+ printk("PCI CONFIG READ access to %d required %d retries\n", offset,
+ (PCI_CFG_RETRY - retry));
+#endif
+
+ return (val);
+}
+
+void
+osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
+{
+ uint retry = PCI_CFG_RETRY;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ ASSERT(size == 4);
+
+ do {
+ pci_write_config_dword(osh->pdev, offset, val);
+ if (offset != PCI_BAR0_WIN)
+ break;
+ if (osl_pci_read_config(osh, offset, size) == val)
+ break;
+ } while (retry--);
+
+#ifdef BCMDBG
+ if (retry < PCI_CFG_RETRY)
+ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset,
+ (PCI_CFG_RETRY - retry));
+#endif
+}
+
+uint
+osl_pci_bus(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return ((struct pci_dev *)osh->pdev)->bus->number;
+}
+
+uint
+osl_pci_slot(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1;
+#else
+ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
+#endif
+}
+
+struct pci_dev *
+osl_pci_device(osl_t *osh)
+{
+ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
+
+ return osh->pdev;
+}
+
+static void
+osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write)
+{
+}
+
+void
+osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
+}
+
+void
+osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size)
+{
+ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
+}
+
+#ifdef BCMDBG_MEM
+
+static
+#endif
+void *
+osl_malloc(osl_t *osh, uint size)
+{
+ void *addr;
+
+ if (osh)
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+
+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
+ if (osh)
+ osh->failed++;
+ return (NULL);
+ }
+ if (osh)
+ atomic_add(size, &osh->malloced);
+
+ return (addr);
+}
+
+#ifdef BCMDBG_MEM
+
+static
+#endif
+void
+osl_mfree(osl_t *osh, void *addr, uint size)
+{
+ if (osh) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ atomic_sub(size, &osh->malloced);
+ }
+ kfree(addr);
+}
+
+uint
+osl_malloced(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (atomic_read(&osh->malloced));
+}
+
+uint
+osl_malloc_failed(osl_t *osh)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ return (osh->failed);
+}
+
+#ifdef BCMDBG_MEM
+#define MEMLIST_LOCK(osh, flags) spin_lock_irqsave(&(osh)->dbgmem_lock, flags)
+#define MEMLIST_UNLOCK(osh, flags) spin_unlock_irqrestore(&(osh)->dbgmem_lock, flags)
+
+void *
+osl_debug_malloc(osl_t *osh, uint size, int line, const char* file)
+{
+ bcm_mem_link_t *p;
+ const char* basename;
+ unsigned long flags = 0;
+
+ if (!size) {
+ printk("%s: allocating zero sized mem at %s line %d\n", __FUNCTION__, file, line);
+ ASSERT(0);
+ }
+
+ if (osh) {
+ MEMLIST_LOCK(osh, flags);
+ }
+ if ((p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size)) == NULL) {
+ if (osh) {
+ MEMLIST_UNLOCK(osh, flags);
+ }
+ return (NULL);
+ }
+
+ p->size = size;
+ p->line = line;
+ p->osh = (void *)osh;
+
+ basename = strrchr(file, '/');
+
+ if (basename)
+ basename++;
+
+ if (!basename)
+ basename = file;
+
+ strncpy(p->file, basename, BCM_MEM_FILENAME_LEN);
+ p->file[BCM_MEM_FILENAME_LEN - 1] = '\0';
+
+ if (osh) {
+ p->prev = NULL;
+ p->next = osh->dbgmem_list;
+ if (p->next)
+ p->next->prev = p;
+ osh->dbgmem_list = p;
+ MEMLIST_UNLOCK(osh, flags);
+ }
+
+ return p + 1;
+}
+
+void
+osl_debug_mfree(osl_t *osh, void *addr, uint size, int line, const char* file)
+{
+ bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t));
+ unsigned long flags = 0;
+
+ ASSERT(osh == NULL || osh->magic == OS_HANDLE_MAGIC);
+
+ if (p->size == 0) {
+ printk("osl_debug_mfree: double free on addr %p size %d at line %d file %s\n",
+ addr, size, line, file);
+ ASSERT(p->size);
+ return;
+ }
+
+ if (p->size != size) {
+ printk("%s: dealloca size does not match alloc size\n", __FUNCTION__);
+ printk("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
+ printk("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
+ ASSERT(p->size == size);
+ return;
+ }
+
+ if (p->osh != (void *)osh) {
+ printk("osl_debug_mfree: alloc osh %p does not match dealloc osh %p\n",
+ p->osh, osh);
+ printk("Dealloc addr %p size %d at line %d file %s\n", addr, size, line, file);
+ printk("Alloc size %d line %d file %s\n", p->size, p->line, p->file);
+ ASSERT(p->osh == (void *)osh);
+ return;
+ }
+
+ if (osh) {
+ MEMLIST_LOCK(osh, flags);
+ if (p->prev)
+ p->prev->next = p->next;
+ if (p->next)
+ p->next->prev = p->prev;
+ if (osh->dbgmem_list == p)
+ osh->dbgmem_list = p->next;
+ p->next = p->prev = NULL;
+ }
+ p->size = 0;
+
+ osl_mfree(osh, p, size + sizeof(bcm_mem_link_t));
+ if (osh) {
+ MEMLIST_UNLOCK(osh, flags);
+ }
+}
+
+int
+osl_debug_memdump(osl_t *osh, struct bcmstrbuf *b)
+{
+ bcm_mem_link_t *p;
+ unsigned long flags = 0;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ MEMLIST_LOCK(osh, flags);
+ if (osh->dbgmem_list) {
+ if (b != NULL)
+ bcm_bprintf(b, " Address Size File:line\n");
+ else
+ printf(" Address Size File:line\n");
+
+ for (p = osh->dbgmem_list; p; p = p->next) {
+ if (b != NULL)
+ bcm_bprintf(b, "%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
+ p->size, p->file, p->line);
+ else
+ printf("%p %6d %s:%d\n", (char*)p + sizeof(bcm_mem_link_t),
+ p->size, p->file, p->line);
+
+ if (p == p->next) {
+ if (b != NULL)
+ bcm_bprintf(b, "WARNING: loop-to-self "
+ "p %p p->next %p\n", p, p->next);
+ else
+ printf("WARNING: loop-to-self "
+ "p %p p->next %p\n", p, p->next);
+
+ break;
+ }
+ }
+ }
+ MEMLIST_UNLOCK(osh, flags);
+
+ return 0;
+}
+
+#endif
+
+uint
+osl_dma_consistent_align(void)
+{
+ return (PAGE_SIZE);
+}
+
+void*
+osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap)
+{
+ void *va;
+ uint16 align = (1 << align_bits);
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
+ size += align;
+ *alloced = size;
+
+#ifdef __ARM_ARCH_7A__
+ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
+ if (va)
+ *pap = (ulong)__virt_to_phys(va);
+#else
+ va = pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap);
+#endif
+ return va;
+}
+
+void
+osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa)
+{
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+#ifdef __ARM_ARCH_7A__
+ kfree(va);
+#else
+ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
+#endif
+}
+
+uint BCMFASTPATH
+osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+
+#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL)
+ if (dmah != NULL) {
+ int32 nsegs, i, totsegs = 0, totlen = 0;
+ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2];
+ struct sk_buff *skb;
+ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) {
+ sg = &_sg[totsegs];
+ if (skb_is_nonlinear(skb)) {
+ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb));
+ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS));
+ pci_map_sg(osh->pdev, sg, nsegs, dir);
+ } else {
+ nsegs = 1;
+ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS);
+ sg->page_link = 0;
+ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb));
+ pci_map_single(osh->pdev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir);
+ }
+ totsegs += nsegs;
+ totlen += PKTLEN(osh, skb);
+ }
+ dmah->nsegs = totsegs;
+ dmah->origsize = totlen;
+ for (i = 0, sg = _sg; i < totsegs; i++, sg++) {
+ dmah->segs[i].addr = sg_phys(sg);
+ dmah->segs[i].length = sg->length;
+ }
+ return dmah->segs[0].addr;
+ }
+#endif
+
+ return (pci_map_single(osh->pdev, va, size, dir));
+}
+
+void BCMFASTPATH
+osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction)
+{
+ int dir;
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+ pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
+}
+
+#if defined(BCMDBG_ASSERT)
+void
+osl_assert(const char *exp, const char *file, int line)
+{
+ char tempbuf[256];
+ const char *basename;
+
+ basename = strrchr(file, '/');
+
+ if (basename)
+ basename++;
+
+ if (!basename)
+ basename = file;
+
+#ifdef BCMDBG_ASSERT
+ snprintf(tempbuf, 256, "assertion \"%s\" failed: file \"%s\", line %d\n",
+ exp, basename, line);
+
+ if (!in_interrupt() && g_assert_type != 1) {
+ const int delay = 3;
+ printk("%s", tempbuf);
+ printk("panic in %d seconds\n", delay);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(delay * HZ);
+ }
+
+ switch (g_assert_type) {
+ case 0:
+ panic("%s", tempbuf);
+ break;
+ case 1:
+ printk("%s", tempbuf);
+ break;
+ case 2:
+ printk("%s", tempbuf);
+ BUG();
+ break;
+ default:
+ break;
+ }
+#endif
+
+}
+#endif
+
+void
+osl_delay(uint usec)
+{
+ uint d;
+
+ while (usec > 0) {
+ d = MIN(usec, 1000);
+ udelay(d);
+ usec -= d;
+ }
+}
+
+void *
+osl_pktdup(osl_t *osh, void *skb)
+{
+ void * p;
+
+ ASSERT(!PKTISCHAINED(skb));
+
+ PKTCTFMAP(osh, skb);
+
+ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL)
+ return NULL;
+
+ PKTSETCLINK(p, NULL);
+ PKTCCLRFLAGS(p);
+ PKTCSETCNT(p, 1);
+ PKTCSETLEN(p, PKTLEN(osh, skb));
+
+ if (osh->pub.pkttag)
+ OSL_PKTTAG_CLEAR(p);
+
+ atomic_inc(&osh->pktalloced);
+ return (p);
+}
+
+uint32
+osl_sysuptime(void)
+{
+ return ((uint32)jiffies * (1000 / HZ));
+}
+
+int
+osl_printf(const char *format, ...)
+{
+ va_list args;
+ static char printbuf[1024];
+ int len;
+
+ va_start(args, format);
+ len = vsnprintf(printbuf, 1024, format, args);
+ va_end(args);
+
+ if (len > sizeof(printbuf)) {
+ printk("osl_printf: buffer overrun\n");
+ return (0);
+ }
+
+ return (printk("%s", printbuf));
+}
+
+int
+osl_sprintf(char *buf, const char *format, ...)
+{
+ va_list args;
+ int rc;
+
+ va_start(args, format);
+ rc = vsprintf(buf, format, args);
+ va_end(args);
+ return (rc);
+}
+
+int
+osl_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ va_list args;
+ int rc;
+
+ va_start(args, format);
+ rc = vsnprintf(buf, n, format, args);
+ va_end(args);
+ return (rc);
+}
+
+int
+osl_vsprintf(char *buf, const char *format, va_list ap)
+{
+ return (vsprintf(buf, format, ap));
+}
+
+int
+osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap)
+{
+ return (vsnprintf(buf, n, format, ap));
+}
+
+int
+osl_strcmp(const char *s1, const char *s2)
+{
+ return (strcmp(s1, s2));
+}
+
+int
+osl_strncmp(const char *s1, const char *s2, uint n)
+{
+ return (strncmp(s1, s2, n));
+}
+
+int
+osl_strlen(const char *s)
+{
+ return (strlen(s));
+}
+
+char*
+osl_strcpy(char *d, const char *s)
+{
+ return (strcpy(d, s));
+}
+
+char*
+osl_strncpy(char *d, const char *s, uint n)
+{
+ return (strncpy(d, s, n));
+}
+
+char*
+osl_strchr(const char *s, int c)
+{
+ return (strchr(s, c));
+}
+
+char*
+osl_strrchr(const char *s, int c)
+{
+ return (strrchr(s, c));
+}
+
+void*
+osl_memset(void *d, int c, size_t n)
+{
+ return memset(d, c, n);
+}
+
+void*
+osl_memcpy(void *d, const void *s, size_t n)
+{
+ return memcpy(d, s, n);
+}
+
+void*
+osl_memmove(void *d, const void *s, size_t n)
+{
+ return memmove(d, s, n);
+}
+
+int
+osl_memcmp(const void *s1, const void *s2, size_t n)
+{
+ return memcmp(s1, s2, n);
+}
+
+uint32
+osl_readl(volatile uint32 *r)
+{
+ return (readl(r));
+}
+
+uint16
+osl_readw(volatile uint16 *r)
+{
+ return (readw(r));
+}
+
+uint8
+osl_readb(volatile uint8 *r)
+{
+ return (readb(r));
+}
+
+void
+osl_writel(uint32 v, volatile uint32 *r)
+{
+ writel(v, r);
+}
+
+void
+osl_writew(uint16 v, volatile uint16 *r)
+{
+ writew(v, r);
+}
+
+void
+osl_writeb(uint8 v, volatile uint8 *r)
+{
+ writeb(v, r);
+}
+
+void *
+osl_uncached(void *va)
+{
+ return ((void*)va);
+}
+
+void *
+osl_cached(void *va)
+{
+ return ((void*)va);
+}
+
+uint
+osl_getcycles(void)
+{
+ uint cycles;
+
+#if defined(__i386__)
+ rdtscl(cycles);
+#else
+ cycles = 0;
+#endif
+ return cycles;
+}
+
+void *
+osl_reg_map(uint32 pa, uint size)
+{
+ return (ioremap_nocache((unsigned long)pa, (unsigned long)size));
+}
+
+void
+osl_reg_unmap(void *va)
+{
+ iounmap(va);
+}
+
+int
+osl_busprobe(uint32 *val, uint32 addr)
+{
+ *val = readl((uint32 *)(uintptr)addr);
+ return 0;
+}
+
+bool
+osl_pktshared(void *skb)
+{
+ return (((struct sk_buff*)skb)->cloned);
+}
+
+uchar*
+osl_pktdata(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->data);
+}
+
+uint
+osl_pktlen(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->len);
+}
+
+uint
+osl_pktheadroom(osl_t *osh, void *skb)
+{
+ return (uint) skb_headroom((struct sk_buff *) skb);
+}
+
+uint
+osl_pkttailroom(osl_t *osh, void *skb)
+{
+ return (uint) skb_tailroom((struct sk_buff *) skb);
+}
+
+void*
+osl_pktnext(osl_t *osh, void *skb)
+{
+ return (((struct sk_buff*)skb)->next);
+}
+
+void
+osl_pktsetnext(void *skb, void *x)
+{
+ ((struct sk_buff*)skb)->next = (struct sk_buff*)x;
+}
+
+void
+osl_pktsetlen(osl_t *osh, void *skb, uint len)
+{
+ __skb_trim((struct sk_buff*)skb, len);
+}
+
+uchar*
+osl_pktpush(osl_t *osh, void *skb, int bytes)
+{
+ return (skb_push((struct sk_buff*)skb, bytes));
+}
+
+uchar*
+osl_pktpull(osl_t *osh, void *skb, int bytes)
+{
+ return (skb_pull((struct sk_buff*)skb, bytes));
+}
+
+void*
+osl_pkttag(void *skb)
+{
+ return ((void*)(((struct sk_buff*)skb)->cb));
+}
+
+void*
+osl_pktlink(void *skb)
+{
+ return (((struct sk_buff*)skb)->prev);
+}
+
+void
+osl_pktsetlink(void *skb, void *x)
+{
+ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x;
+}
+
+uint
+osl_pktprio(void *skb)
+{
+ return (((struct sk_buff*)skb)->priority);
+}
+
+void
+osl_pktsetprio(void *skb, uint x)
+{
+ ((struct sk_buff*)skb)->priority = x;
+}
+
+uint
+osl_pktalloced(osl_t *osh)
+{
+ return (atomic_read(&osh->pktalloced));
+}
+
+void *
+osl_os_open_image(char *filename)
+{
+ struct file *fp;
+
+ fp = filp_open(filename, O_RDONLY, 0);
+
+ if (IS_ERR(fp))
+ fp = NULL;
+
+ return fp;
+}
+
+int
+osl_os_get_image_block(char *buf, int len, void *image)
+{
+ struct file *fp = (struct file *)image;
+ int rdlen;
+
+ if (!image)
+ return 0;
+
+ rdlen = kernel_read(fp, fp->f_pos, buf, len);
+ if (rdlen > 0)
+ fp->f_pos += rdlen;
+
+ return rdlen;
+}
+
+void
+osl_os_close_image(void *image)
+{
+ if (image)
+ filp_close((struct file *)image, NULL);
+}
+
+int
+osl_os_image_size(void *image)
+{
+ int len = 0, curroffset;
+
+ if (image) {
+
+ curroffset = generic_file_llseek(image, 0, 1);
+
+ len = generic_file_llseek(image, 0, 2);
+
+ generic_file_llseek(image, curroffset, 0);
+ }
+ return len;
+}
diff --git a/src/wl/sys/wl_cfg80211_hybrid.c b/src/wl/sys/wl_cfg80211_hybrid.c
new file mode 100644
index 0000000..7b606e0
--- /dev/null
+++ b/src/wl/sys/wl_cfg80211_hybrid.c
@@ -0,0 +1,3022 @@
+/*
+ * Linux-specific portion of Broadcom 802.11abg Networking Device Driver
+ * cfg80211 interface
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_cfg80211.c,v 1.1.6.4 2011-02-11 00:22:09 $
+ */
+
+#if defined(USE_CFG80211)
+
+#define LINUX_PORT
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <linux/nl80211.h>
+#include <net/rtnetlink.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <wlioctl.h>
+#include <proto/802.11.h>
+#include <wl_cfg80211_hybrid.h>
+
+#define EVENT_TYPE(e) dtoh32((e)->event_type)
+#define EVENT_FLAGS(e) dtoh16((e)->flags)
+#define EVENT_STATUS(e) dtoh32((e)->status)
+
+#ifdef BCMDBG
+u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
+#else
+u32 wl_dbg_level = WL_DBG_ERR;
+#endif
+
+static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags, struct vif_params *params);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request);
+#else
+static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_scan_request *request);
+#endif
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params);
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, u8 *mac, struct station_info *sinfo);
+#else
+static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+ struct net_device *dev, const u8 *mac, struct station_info *sinfo);
+#endif
+
+static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+ struct net_device *dev, bool enabled, s32 timeout);
+static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 dbm);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, s32 dbm);
+#else
+static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+ enum tx_power_setting type, s32 dbm);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm);
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx, bool unicast, bool multicast);
+#else
+static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params);
+static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr);
+static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
+ void *cookie, void (*callback) (void *cookie, struct key_params *params));
+#else
+static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, struct key_params *params);
+static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr);
+static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr,
+ void *cookie, void (*callback) (void *cookie, struct key_params *params));
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
+#endif
+
+static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl);
+static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl);
+static s32 wl_event_handler(void *data);
+static void wl_init_eq(struct wl_cfg80211_priv *wl);
+static void wl_flush_eq(struct wl_cfg80211_priv *wl);
+static void wl_lock_eq(struct wl_cfg80211_priv *wl);
+static void wl_unlock_eq(struct wl_cfg80211_priv *wl);
+static void wl_init_eq_lock(struct wl_cfg80211_priv *wl);
+static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el);
+static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl);
+static s32 wl_enq_event(struct wl_cfg80211_priv *wl, u32 type,
+ const wl_event_msg_t *msg, void *data);
+static void wl_put_event(struct wl_cfg80211_event_q *e);
+static void wl_wakeup_event(struct wl_cfg80211_priv *wl);
+
+static s32 wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed);
+static s32 wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+static s32 wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+
+static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len);
+static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len);
+static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
+static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval);
+static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len);
+
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+
+static void wl_init_prof(struct wl_cfg80211_profile *prof);
+
+static s32 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme);
+static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl);
+static void wl_ch_to_chanspec(struct ieee80211_channel *chan,
+ struct wl_join_params *join_params, size_t *join_params_size);
+
+static void wl_rst_ie(struct wl_cfg80211_priv *wl);
+static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v);
+static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size);
+static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size);
+static u32 wl_get_ielen(struct wl_cfg80211_priv *wl);
+
+static s32 wl_mode_to_nl80211_iftype(s32 mode);
+
+static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev);
+static void wl_free_wdev(struct wl_cfg80211_priv *wl);
+
+static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list);
+static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi);
+static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl);
+
+static void key_endian_to_device(struct wl_wsec_key *key);
+static void key_endian_to_host(struct wl_wsec_key *key);
+
+static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl);
+static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl);
+
+static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl);
+
+static void wl_link_up(struct wl_cfg80211_priv *wl);
+static void wl_link_down(struct wl_cfg80211_priv *wl);
+static s32 wl_set_mode(struct net_device *ndev, s32 iftype);
+
+static void wl_init_conf(struct wl_cfg80211_conf *conf);
+
+static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl);
+
+static __used s32 wl_update_pmklist(struct net_device *dev,
+ struct wl_cfg80211_pmk_list *pmk_list, s32 err);
+
+#if defined(WL_DBGMSG_ENABLE)
+#define WL_DBG_ESTR_MAX 32
+static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
+ "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
+ "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
+ "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
+ "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
+ "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
+ "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
+ "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
+ "PFN_NET_LOST",
+ "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
+ "IBSS_ASSOC",
+ "RADIO", "PSM_WATCHDOG",
+ "PROBREQ_MSG",
+ "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
+ "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
+ "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
+ "IF",
+ "RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
+};
+#endif
+
+#define CHAN2G(_channel, _freq, _flags) { \
+ .band = IEEE80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define CHAN5G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 5000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
+
+#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
+#define RATETAB_ENT(_rateid, _flags) \
+ { \
+ .bitrate = RATE_TO_BASE100KBPS(_rateid), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
+ }
+
+static struct ieee80211_rate __wl_rates[] = {
+ RATETAB_ENT(DOT11_RATE_1M, 0),
+ RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(DOT11_RATE_6M, 0),
+ RATETAB_ENT(DOT11_RATE_9M, 0),
+ RATETAB_ENT(DOT11_RATE_12M, 0),
+ RATETAB_ENT(DOT11_RATE_18M, 0),
+ RATETAB_ENT(DOT11_RATE_24M, 0),
+ RATETAB_ENT(DOT11_RATE_36M, 0),
+ RATETAB_ENT(DOT11_RATE_48M, 0),
+ RATETAB_ENT(DOT11_RATE_54M, 0),
+};
+
+#define wl_a_rates (__wl_rates + 4)
+#define wl_a_rates_size 8
+#define wl_g_rates (__wl_rates + 0)
+#define wl_g_rates_size 12
+
+static struct ieee80211_channel __wl_2ghz_channels[] = {
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_a_channels[] = {
+ CHAN5G(34, 0), CHAN5G(36, 0),
+ CHAN5G(38, 0), CHAN5G(40, 0),
+ CHAN5G(42, 0), CHAN5G(44, 0),
+ CHAN5G(46, 0), CHAN5G(48, 0),
+ CHAN5G(52, 0), CHAN5G(56, 0),
+ CHAN5G(60, 0), CHAN5G(64, 0),
+ CHAN5G(100, 0), CHAN5G(104, 0),
+ CHAN5G(108, 0), CHAN5G(112, 0),
+ CHAN5G(116, 0), CHAN5G(120, 0),
+ CHAN5G(124, 0), CHAN5G(128, 0),
+ CHAN5G(132, 0), CHAN5G(136, 0),
+ CHAN5G(140, 0), CHAN5G(149, 0),
+ CHAN5G(153, 0), CHAN5G(157, 0),
+ CHAN5G(161, 0), CHAN5G(165, 0),
+ CHAN5G(184, 0), CHAN5G(188, 0),
+ CHAN5G(192, 0), CHAN5G(196, 0),
+ CHAN5G(200, 0), CHAN5G(204, 0),
+ CHAN5G(208, 0), CHAN5G(212, 0),
+ CHAN5G(216, 0),
+};
+
+static struct ieee80211_channel __wl_5ghz_n_channels[] = {
+ CHAN5G(32, 0), CHAN5G(34, 0),
+ CHAN5G(36, 0), CHAN5G(38, 0),
+ CHAN5G(40, 0), CHAN5G(42, 0),
+ CHAN5G(44, 0), CHAN5G(46, 0),
+ CHAN5G(48, 0), CHAN5G(50, 0),
+ CHAN5G(52, 0), CHAN5G(54, 0),
+ CHAN5G(56, 0), CHAN5G(58, 0),
+ CHAN5G(60, 0), CHAN5G(62, 0),
+ CHAN5G(64, 0), CHAN5G(66, 0),
+ CHAN5G(68, 0), CHAN5G(70, 0),
+ CHAN5G(72, 0), CHAN5G(74, 0),
+ CHAN5G(76, 0), CHAN5G(78, 0),
+ CHAN5G(80, 0), CHAN5G(82, 0),
+ CHAN5G(84, 0), CHAN5G(86, 0),
+ CHAN5G(88, 0), CHAN5G(90, 0),
+ CHAN5G(92, 0), CHAN5G(94, 0),
+ CHAN5G(96, 0), CHAN5G(98, 0),
+ CHAN5G(100, 0), CHAN5G(102, 0),
+ CHAN5G(104, 0), CHAN5G(106, 0),
+ CHAN5G(108, 0), CHAN5G(110, 0),
+ CHAN5G(112, 0), CHAN5G(114, 0),
+ CHAN5G(116, 0), CHAN5G(118, 0),
+ CHAN5G(120, 0), CHAN5G(122, 0),
+ CHAN5G(124, 0), CHAN5G(126, 0),
+ CHAN5G(128, 0), CHAN5G(130, 0),
+ CHAN5G(132, 0), CHAN5G(134, 0),
+ CHAN5G(136, 0), CHAN5G(138, 0),
+ CHAN5G(140, 0), CHAN5G(142, 0),
+ CHAN5G(144, 0), CHAN5G(145, 0),
+ CHAN5G(146, 0), CHAN5G(147, 0),
+ CHAN5G(148, 0), CHAN5G(149, 0),
+ CHAN5G(150, 0), CHAN5G(151, 0),
+ CHAN5G(152, 0), CHAN5G(153, 0),
+ CHAN5G(154, 0), CHAN5G(155, 0),
+ CHAN5G(156, 0), CHAN5G(157, 0),
+ CHAN5G(158, 0), CHAN5G(159, 0),
+ CHAN5G(160, 0), CHAN5G(161, 0),
+ CHAN5G(162, 0), CHAN5G(163, 0),
+ CHAN5G(164, 0), CHAN5G(165, 0),
+ CHAN5G(166, 0), CHAN5G(168, 0),
+ CHAN5G(170, 0), CHAN5G(172, 0),
+ CHAN5G(174, 0), CHAN5G(176, 0),
+ CHAN5G(178, 0), CHAN5G(180, 0),
+ CHAN5G(182, 0), CHAN5G(184, 0),
+ CHAN5G(186, 0), CHAN5G(188, 0),
+ CHAN5G(190, 0), CHAN5G(192, 0),
+ CHAN5G(194, 0), CHAN5G(196, 0),
+ CHAN5G(198, 0), CHAN5G(200, 0),
+ CHAN5G(202, 0), CHAN5G(204, 0),
+ CHAN5G(206, 0), CHAN5G(208, 0),
+ CHAN5G(210, 0), CHAN5G(212, 0),
+ CHAN5G(214, 0), CHAN5G(216, 0),
+ CHAN5G(218, 0), CHAN5G(220, 0),
+ CHAN5G(222, 0), CHAN5G(224, 0),
+ CHAN5G(226, 0), CHAN5G(228, 0),
+};
+
+static struct ieee80211_supported_band __wl_band_2ghz = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = __wl_2ghz_channels,
+ .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
+ .bitrates = wl_g_rates,
+ .n_bitrates = wl_g_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_a = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = __wl_5ghz_a_channels,
+ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
+ .bitrates = wl_a_rates,
+ .n_bitrates = wl_a_rates_size,
+};
+
+static struct ieee80211_supported_band __wl_band_5ghz_n = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = __wl_5ghz_n_channels,
+ .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
+ .bitrates = wl_a_rates,
+ .n_bitrates = wl_a_rates_size,
+};
+
+static const u32 __wl_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+};
+
+static void key_endian_to_device(struct wl_wsec_key *key)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void key_endian_to_host(struct wl_wsec_key *key)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static s32
+wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+{
+ struct ifreq ifr;
+ struct wl_ioctl ioc;
+ mm_segment_t fs;
+ s32 err = 0;
+
+ BUG_ON(len < sizeof(int));
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t)&ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if defined(WL_USE_NETDEV_OPS)
+ err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wireless_dev *wdev;
+ s32 infra = 0;
+ s32 ap = 0;
+ s32 err = 0;
+
+ switch (type) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ WL_ERR(("type (%d) : currently we do not support this type\n",
+ type));
+ return -EOPNOTSUPP;
+ case NL80211_IFTYPE_ADHOC:
+ wl->conf->mode = WL_MODE_IBSS;
+ break;
+ case NL80211_IFTYPE_STATION:
+ wl->conf->mode = WL_MODE_BSS;
+ infra = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+ wdev = ndev->ieee80211_ptr;
+ wdev->iftype = type;
+ WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
+ err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ if (err) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return err;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
+ if (err) {
+ WL_ERR(("WLC_SET_AP error (%d)\n", err));
+ return err;
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request)
+#else
+static s32
+wl_cfg80211_scan(struct wiphy *wiphy,
+ struct net_device *ndev,
+ struct cfg80211_scan_request *request)
+#endif
+
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ struct net_device *ndev = request->wdev->netdev;
+#endif
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ struct cfg80211_ssid *ssids;
+ struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
+ s32 passive_scan;
+ s32 err = 0;
+
+ if (request) {
+ ssids = request->ssids;
+ }
+ else {
+
+ ssids = NULL;
+ }
+ wl->scan_request = request;
+
+ memset(&sr->ssid, 0, sizeof(sr->ssid));
+
+ if (ssids) {
+ WL_DBG(("ssid \"%s\", ssid_len (%d)\n", ssids->ssid, ssids->ssid_len));
+ sr->ssid.SSID_len = min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
+ }
+
+ if (sr->ssid.SSID_len) {
+ memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
+ sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+ WL_DBG(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID, sr->ssid.SSID_len));
+ } else {
+ WL_DBG(("Broadcast scan\n"));
+ }
+ WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
+ passive_scan = wl->active_scan ? 0 : 1;
+ err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan));
+ if (err) {
+ WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
+ goto scan_out;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid, sizeof(sr->ssid));
+ if (err) {
+ if (err == -EBUSY) {
+ WL_INF(("system busy : scan for \"%s\" "
+ "canceled\n", sr->ssid.SSID));
+ } else {
+ WL_ERR(("WLC_SCAN error (%d)\n", err));
+ }
+ goto scan_out;
+ }
+
+ return 0;
+
+scan_out:
+ wl->scan_request = NULL;
+ return err;
+}
+
+static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+{
+ s8 buf[WLC_IOCTL_SMLEN];
+ u32 len;
+ s32 err = 0;
+
+ val = htod32(val);
+ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ BUG_ON(!len);
+
+ err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ }
+
+ return err;
+}
+
+static s32
+wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
+{
+ union {
+ s8 buf[WLC_IOCTL_SMLEN];
+ s32 val;
+ } var;
+ u32 len;
+ u32 data_null;
+ s32 err = 0;
+
+ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+ BUG_ON(!len);
+ err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ }
+ *retval = dtoh32(var.val);
+
+ return err;
+}
+
+static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+{
+ s32 err = 0;
+
+ err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+{
+ s32 err = 0;
+
+ err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+{
+ s32 err = 0;
+ u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+
+ retry = htod32(retry);
+ err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+ if (err) {
+ WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ s32 err = 0;
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+ (wl->conf->rts_threshold != wiphy->rts_threshold)) {
+ wl->conf->rts_threshold = wiphy->rts_threshold;
+ err = wl_set_rts(ndev, wl->conf->rts_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+ (wl->conf->frag_threshold != wiphy->frag_threshold)) {
+ wl->conf->frag_threshold = wiphy->frag_threshold;
+ err = wl_set_frag(ndev, wl->conf->frag_threshold);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_LONG && (wl->conf->retry_long != wiphy->retry_long)) {
+ wl->conf->retry_long = wiphy->retry_long;
+ err = wl_set_retry(ndev, wl->conf->retry_long, true);
+ if (!err)
+ return err;
+ }
+ if (changed & WIPHY_PARAM_RETRY_SHORT && (wl->conf->retry_short != wiphy->retry_short)) {
+ wl->conf->retry_short = wiphy->retry_short;
+ err = wl_set_retry(ndev, wl->conf->retry_short, false);
+ if (!err) {
+ return err;
+ }
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ibss_params *params)
+{
+ struct wl_join_params join_params;
+ size_t join_params_size;
+ s32 val;
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ if (params->bssid) {
+ WL_ERR(("Invalid bssid\n"));
+ return -EOPNOTSUPP;
+ }
+
+ if ((err = wl_dev_intvar_set(dev, "auth", 0))) {
+ return err;
+ }
+ if ((err = wl_dev_intvar_set(dev, "wpa_auth", WPA_AUTH_NONE))) {
+ return err;
+ }
+ if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
+ return err;
+ }
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ if ((err = wl_dev_intvar_set(dev, "wsec", val))) {
+ return err;
+ }
+
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len);
+ join_params.ssid.SSID_len = htod32(params->ssid_len);
+ if (params->bssid)
+ memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
+ else
+ memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ wl_ch_to_chanspec(params->chandef.chan, &join_params, &join_params_size);
+#else
+ wl_ch_to_chanspec(params->channel, &join_params, &join_params_size);
+#endif
+ err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ if (err) {
+ WL_ERR(("Error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ wl_link_down(wl);
+
+ return err;
+}
+
+static s32
+wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ else
+ val = WPA_AUTH_DISABLED;
+ WL_DBG(("setting wpa_auth to 0x%0x\n", val));
+ err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ if (err) {
+ WL_ERR(("set wpa_auth failed (%d)\n", err));
+ return err;
+ }
+ wl->profile->sec.wpa_versions = sme->crypto.wpa_versions;
+ return err;
+}
+
+static s32
+wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ switch (sme->auth_type) {
+ case NL80211_AUTHTYPE_OPEN_SYSTEM:
+ val = 0;
+ WL_DBG(("open system\n"));
+ break;
+ case NL80211_AUTHTYPE_SHARED_KEY:
+ val = 1;
+ WL_DBG(("shared key\n"));
+ break;
+ case NL80211_AUTHTYPE_AUTOMATIC:
+ val = 2;
+ WL_DBG(("automatic\n"));
+ break;
+ case NL80211_AUTHTYPE_NETWORK_EAP:
+ WL_DBG(("network eap\n"));
+ default:
+ val = 2;
+ WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
+ break;
+ }
+
+ err = wl_dev_intvar_set(dev, "auth", val);
+ if (err) {
+ WL_ERR(("set auth failed (%d)\n", err));
+ return err;
+ }
+
+ wl->profile->sec.auth_type = sme->auth_type;
+ return err;
+}
+
+static s32
+wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 pval = 0;
+ s32 gval = 0;
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.n_ciphers_pairwise) {
+ switch (sme->crypto.ciphers_pairwise[0]) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ pval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ pval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ pval = AES_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ pval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+ }
+ if (sme->crypto.cipher_group) {
+ switch (sme->crypto.cipher_group) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ gval = WEP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ gval = TKIP_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ gval = AES_ENABLED;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ gval = AES_ENABLED;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ }
+
+ if ((err = wl_dev_intvar_get(dev, "wsec", &val))) {
+ return err;
+ }
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ val |= pval | gval;
+ WL_DBG(("set wsec to %d\n", val));
+ err = wl_dev_intvar_set(dev, "wsec", val);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ wl->profile->sec.cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+ wl->profile->sec.cipher_group = sme->crypto.cipher_group;
+
+ return err;
+}
+
+static s32
+wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ s32 val = 0;
+ s32 err = 0;
+
+ if (sme->crypto.n_akm_suites) {
+ err = wl_dev_intvar_get(dev, "wpa_auth", &val);
+ if (err) {
+ WL_ERR(("could not get wpa_auth (%d)\n", err));
+ return err;
+ }
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ switch (sme->crypto.akm_suites[0]) {
+ case WLAN_AKM_SUITE_8021X:
+ val = WPA2_AUTH_UNSPECIFIED;
+ break;
+ case WLAN_AKM_SUITE_PSK:
+ val = WPA2_AUTH_PSK;
+ break;
+ default:
+ WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
+ return -EINVAL;
+ }
+ }
+
+ WL_DBG(("setting wpa_auth to %d\n", val));
+ err = wl_dev_intvar_set(dev, "wpa_auth", val);
+ if (err) {
+ WL_ERR(("could not set wpa_auth (%d)\n", err));
+ return err;
+ }
+ }
+
+ wl->profile->sec.wpa_auth = sme->crypto.akm_suites[0];
+
+ return err;
+}
+
+static s32
+wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ struct wl_cfg80211_security *sec;
+ struct wl_wsec_key key;
+ s32 err = 0;
+
+ WL_DBG(("key len (%d)\n", sme->key_len));
+ if (sme->key_len) {
+ sec = &wl->profile->sec;
+ WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
+ sec->wpa_versions, sec->cipher_pairwise));
+ if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
+ (sec->cipher_pairwise &
+ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104))) {
+ memset(&key, 0, sizeof(key));
+ key.len = (u32) sme->key_len;
+ key.index = (u32) sme->key_idx;
+ if (key.len > sizeof(key.data)) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, sme->key, key.len);
+ key.flags = WL_PRIMARY_KEY;
+ switch (sec->cipher_pairwise) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ default:
+ WL_ERR(("Invalid algorithm (%d)\n",
+ sme->crypto.ciphers_pairwise[0]));
+ return -EINVAL;
+ }
+
+ WL_DBG(("key length (%d) key index (%d) algo (%d)\n", key.len,
+ key.index, key.algo));
+ WL_DBG(("key \"%s\"\n", key.data));
+ key_endian_to_device(&key);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+ }
+ }
+ return err;
+}
+
+static s32
+wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wl_join_params join_params;
+ size_t join_params_size;
+ char valc;
+ s32 err = 0;
+
+ if (!sme->ssid) {
+ WL_ERR(("Invalid ssid\n"));
+ return -EOPNOTSUPP;
+ }
+
+ WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
+
+ err = wl_set_auth_type(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_wpa_version(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_set_cipher(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_key_mgmt(dev, sme);
+ if (err)
+ return err;
+
+ err = wl_set_set_sharedkey(dev, sme);
+ if (err)
+ return err;
+
+ valc = 1;
+ wl_dev_bufvar_set(dev, "wsec_restrict", &valc, 1);
+
+ if (sme->bssid) {
+ memcpy(wl->profile->bssid, sme->bssid, ETHER_ADDR_LEN);
+ }
+ else {
+ memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
+ }
+
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+ memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+ memcpy(wl->profile->ssid.SSID, &join_params.ssid.SSID, join_params.ssid.SSID_len);
+ wl->profile->ssid.SSID_len = join_params.ssid.SSID_len;
+
+ wl_ch_to_chanspec(sme->channel, &join_params, &join_params_size);
+ WL_DBG(("join_param_size %u\n", (unsigned int)join_params_size));
+
+ if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_DBG(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
+ join_params.ssid.SSID_len));
+ }
+ err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ set_bit(WL_STATUS_CONNECTING, &wl->status);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ scb_val_t scbval;
+ s32 err = 0;
+
+ WL_DBG(("Reason %d\n", reason_code));
+
+ if (wl->profile->active) {
+ scbval.val = reason_code;
+ memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
+ scbval.val = htod32(scbval.val);
+ err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, s32 dbm)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 dbm)
+#else
+#define NL80211_TX_POWER_AUTOMATIC TX_POWER_AUTOMATIC
+#define NL80211_TX_POWER_LIMITED TX_POWER_LIMITED
+#define NL80211_TX_POWER_FIXED TX_POWER_FIXED
+static s32
+wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, s32 dbm)
+#endif
+{
+
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ u16 txpwrmw;
+ s32 err = 0;
+ s32 disable = 0;
+
+ switch (type) {
+ case NL80211_TX_POWER_AUTOMATIC:
+ break;
+ case NL80211_TX_POWER_LIMITED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
+ return -EINVAL;
+ }
+ break;
+ case NL80211_TX_POWER_FIXED:
+ if (dbm < 0) {
+ WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
+ return -EINVAL;
+ }
+ break;
+ }
+
+ disable = WL_RADIO_SW_DISABLE << 16;
+ disable = htod32(disable);
+ err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+ if (err) {
+ WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
+ return err;
+ }
+
+ if (dbm > 0xffff)
+ txpwrmw = 0xffff;
+ else
+ txpwrmw = (u16) dbm;
+ err = wl_dev_intvar_set(ndev, "qtxpower", (s32) (bcm_mw_to_qdbm(txpwrmw)));
+ if (err) {
+ WL_ERR(("qtxpower error (%d)\n", err));
+ return err;
+ }
+ wl->conf->tx_power = dbm;
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm)
+#else
+static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+#endif
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
+ s32 txpwrdbm;
+ u8 result;
+ s32 err = 0;
+
+ err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
+ *dbm = (s32) bcm_qdbm_to_mw(result);
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx, bool unicast, bool multicast)
+#else
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy,
+ struct net_device *dev, u8 key_idx)
+#endif
+{
+ u32 index;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ index = (u32) key_idx;
+ index = htod32(index);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, sizeof(index));
+ if (err) {
+ WL_DBG(("error (%d)\n", err));
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params)
+#else
+static s32
+wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, struct key_params *params)
+#endif
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ struct wl_wsec_key key;
+ s32 secval, secnew = 0;
+ s32 err = 0;
+
+ WL_DBG(("key index %u len %u\n", (unsigned)key_idx, params->key_len));
+
+ memset(&key, 0, sizeof(key));
+
+ key.index = (u32) key_idx;
+
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key.algo = CRYPTO_ALGO_WEP1;
+ secnew = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ key.algo = CRYPTO_ALGO_WEP128;
+ secnew = WEP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ secnew = TKIP_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ secnew = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ secnew = AES_ENABLED;
+ WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
+ break;
+ default:
+ WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
+ return -EINVAL;
+ }
+
+ if (mac_addr) {
+ if (!ETHER_ISMULTI(mac_addr)) {
+ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+ }
+ }
+
+ key.len = (u32) params->key_len;
+ if (key.len > sizeof(key.data)) {
+ WL_ERR(("Too long key length (%u)\n", key.len));
+ return -EINVAL;
+ }
+ memcpy(key.data, params->key, key.len);
+
+ if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ u8 keybuf[8];
+ memcpy(keybuf, &key.data[24], sizeof(keybuf));
+ memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+ memcpy(&key.data[16], keybuf, sizeof(keybuf));
+ }
+
+ if (params->seq_len) {
+ u8 *ivptr;
+ if (params->seq_len != 6) {
+ WL_ERR(("seq_len %d is unexpected, check implementation.\n",
+ params->seq_len));
+ }
+ ivptr = (u8 *) params->seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = true;
+ }
+
+ key_endian_to_device(&key);
+ if (wl->passive) {
+ schedule();
+ }
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ return err;
+ }
+
+ if ((err = wl_dev_intvar_get(dev, "wsec", &secval))) {
+ return err;
+ }
+ if (secnew == WEP_ENABLED) {
+ secval &= ~(TKIP_ENABLED | AES_ENABLED);
+ }
+ else {
+ secval &= ~(WEP_ENABLED);
+ }
+ secval |= secnew;
+ WL_DBG(("set wsec to %d\n", secval));
+ err = wl_dev_intvar_set(dev, "wsec", secval);
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ if (mac_addr) {
+ wl->profile->sec.cipher_pairwise = params->cipher;
+ }
+ else {
+ wl->profile->sec.cipher_group = params->cipher;
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr)
+#else
+static s32
+wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr)
+#endif
+{
+ struct wl_wsec_key key;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ memset(&key, 0, sizeof(key));
+
+ key.index = (u32) key_idx;
+ key.len = 0;
+ if (mac_addr) {
+ if (!ETHER_ISMULTI(mac_addr)) {
+ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
+ }
+ }
+ key.algo = CRYPTO_ALGO_OFF;
+
+ key_endian_to_device(&key);
+ err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (err) {
+ if (err == -EINVAL) {
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
+
+ WL_DBG(("invalid key index (%d)\n", key_idx));
+ }
+ } else {
+ WL_ERR(("WLC_SET_KEY error (%d)\n", err));
+ }
+ return err;
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+static s32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie, struct key_params * params))
+#else
+static s32
+wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u8 key_idx, const u8 *mac_addr, void *cookie,
+ void (*callback) (void *cookie, struct key_params * params))
+#endif
+{
+ struct key_params params;
+ struct wl_wsec_key key;
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct wl_cfg80211_security *sec;
+ s32 wsec;
+ s32 err = 0;
+
+ WL_DBG(("key index (%d)\n", key_idx));
+
+ memset(&params, 0, sizeof(params));
+
+ memset(&key, 0, sizeof(key));
+ key.index = key_idx;
+ key_endian_to_device(&key);
+
+ if ((err = wl_dev_ioctl(dev, WLC_GET_KEY, &key, sizeof(key)))) {
+ return err;
+ }
+ key_endian_to_host(&key);
+
+ params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+ memcpy((char *)params.key, key.data, params.key_len);
+
+ if ((err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+ return err;
+ }
+ wsec = dtoh32(wsec);
+ switch (wsec) {
+ case WEP_ENABLED:
+ sec = &wl->profile->sec;
+ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ }
+ break;
+ case TKIP_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_TKIP;
+ WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+ break;
+ case AES_ENABLED:
+ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+ WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+ break;
+ default:
+ WL_ERR(("Invalid algo (0x%x)\n", wsec));
+ return -EINVAL;
+ }
+
+ callback(cookie, &params);
+ return err;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_info *sinfo)
+#else
+static s32
+wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *mac, struct station_info *sinfo)
+#endif
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ scb_val_t scb_val;
+ int rssi;
+ s32 rate;
+ s32 err = 0;
+
+ if (memcmp(mac, wl->profile->bssid, ETHER_ADDR_LEN)) {
+ WL_ERR(("Wrong Mac address, mac = %pM profile =%pM\n", mac, wl->profile->bssid));
+ return -ENOENT;
+ }
+
+ err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+ if (err) {
+ WL_DBG(("Could not get rate (%d)\n", err));
+ } else {
+ rate = dtoh32(rate);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+#else
+ sinfo->filled |= STATION_INFO_TX_BITRATE;
+#endif
+ sinfo->txrate.legacy = rate * 5;
+ WL_DBG(("Rate %d Mbps\n", (rate / 2)));
+ }
+
+ if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+ memset(&scb_val, 0, sizeof(scb_val));
+ err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
+ if (err) {
+ WL_DBG(("Could not get rssi (%d)\n", err));
+ return err;
+ }
+ rssi = dtoh32(scb_val.val);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+#else
+ sinfo->filled |= STATION_INFO_SIGNAL;
+#endif
+ sinfo->signal = rssi;
+ WL_DBG(("RSSI %d dBm\n", rssi));
+ }
+
+ return err;
+}
+
+static s32
+wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, s32 timeout)
+{
+ s32 pm;
+ s32 err = 0;
+
+ pm = enabled ? PM_FAST : PM_OFF;
+ pm = htod32(pm);
+ WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
+ err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ if (err) {
+ if (err == -ENODEV)
+ WL_DBG(("net_device is not ready yet\n"));
+ else
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+ return err;
+}
+
+static __used s32
+wl_update_pmklist(struct net_device *dev, struct wl_cfg80211_pmk_list *pmk_list, s32 err)
+{
+ int i, j;
+
+ WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
+ for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ WL_DBG(("PMKID[%d]: %pM =\n", i,
+ &pmk_list->pmkids.pmkid[i].BSSID));
+ for (j = 0; j < WPA2_PMKID_LEN; j++) {
+ WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
+ }
+ }
+ if (!err) {
+ err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list, sizeof(*pmk_list));
+ }
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+
+static s32
+wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+ int i;
+
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+ break;
+ if (i < WL_NUM_PMKIDS_MAX) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+ if (i == wl->pmk_list->pmkids.npmkid)
+ wl->pmk_list->pmkids.npmkid++;
+ } else {
+ err = -EINVAL;
+ }
+ WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
+ &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n",
+ wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i]));
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+ return err;
+}
+
+static s32
+wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ struct _pmkid_list pmkid;
+ s32 err = 0;
+ int i;
+
+ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+
+ WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
+ &pmkid.pmkid[0].BSSID));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
+ }
+
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+ break;
+
+ if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) {
+ memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
+ for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
+ &wl->pmk_list->pmkids.pmkid[i + 1].BSSID, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
+ &wl->pmk_list->pmkids.pmkid[i + 1].PMKID, WPA2_PMKID_LEN);
+ }
+ wl->pmk_list->pmkids.npmkid--;
+ } else {
+ err = -EINVAL;
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+ return err;
+
+}
+
+static s32
+wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ s32 err = 0;
+
+ memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+ return err;
+
+}
+
+#endif
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+
+static int
+wl_wowl_ind_wake_reason(struct wl_cfg80211_priv *wl, struct cfg80211_wowlan_wakeup *wakeup)
+{
+ wl_wowl_wakeind_t wowl_ind;
+ s32 err;
+
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "wowl_wakeind",
+ (s8 *)&wowl_ind, sizeof(wowl_ind));
+ if (err != 0) {
+ WL_ERR(("Unable to get wake reason, err = %d\n", err));
+ return -1;
+ }
+
+ if (wowl_ind.ucode_wakeind == 0) {
+ WL_DBG(("System woke, but not by us\n"));
+ return 0;
+ }
+ WL_DBG(("wake reason is 0x%x\n", wowl_ind.ucode_wakeind));
+
+ if (wowl_ind.ucode_wakeind & WL_WOWL_MAGIC) {
+ WL_ERR(("WOWLAN Woke for: Magic Pkt\n"));
+ wakeup->magic_pkt = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_DIS) {
+ WL_ERR(("WOWLAN Woke for: Disconnect\n"));
+ wakeup->disconnect = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_BCN) {
+ WL_ERR(("WOWLAN Woke for: Beacon Loss\n"));
+ wakeup->disconnect = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_GTK_FAILURE) {
+ WL_ERR(("WOWLAN Woke for: GTK failure\n"));
+ wakeup->gtk_rekey_failure = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_EAPID) {
+ WL_ERR(("WOWLAN Woke for: EAP identify request\n"));
+ wakeup->eap_identity_req = true;
+ }
+ if (wowl_ind.ucode_wakeind & WL_WOWL_M1) {
+ WL_ERR(("WOWLAN Woke for: 4-way handshake request\n"));
+ wakeup->four_way_handshake = true;
+ }
+ return 1;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+static int
+wl_cfg80211_rekey(struct wiphy *wiphy, struct net_device *ndev,
+ struct cfg80211_gtk_rekey_data *data)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ wlc_rekey_info_t rekey;
+ s32 err;
+
+ if (!wl->offloads) {
+ return 0;
+ }
+
+ memset(&rekey, 0, sizeof(rekey));
+ memcpy(&rekey.kek, data->kek, WLC_KEK_LEN);
+ memcpy(&rekey.kck, data->kck, WLC_KCK_LEN);
+ memcpy(&rekey.replay_counter, data->replay_ctr, WLC_REPLAY_CTR_LEN);
+ WL_INF(("Send down replay counter %x%x%x%x%x%x%x%x\n",
+ rekey.replay_counter[0], rekey.replay_counter[1], rekey.replay_counter[2],
+ rekey.replay_counter[3], rekey.replay_counter[4], rekey.replay_counter[5],
+ rekey.replay_counter[6], rekey.replay_counter[7]));
+
+ err = wl_dev_bufvar_set(wl_to_ndev(wl), "wowl_replay", (s8 *)&rekey, sizeof(rekey));
+ if (err) {
+ WL_ERR(("Error calling wowl_set_key\n"));
+ return err;
+ }
+ return err;
+}
+#endif
+
+static int wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan)
+{
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ uint wowl = 0;
+ s32 err;
+
+ if (!wowlan) {
+ WL_DBG(("No wowlan requested\n"));
+ return 0;
+ }
+ if (!test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+ WL_INF(("No wowl when not associated.\n"));
+ return 0;
+ }
+
+ err = wl_dev_intvar_get(wl_to_ndev(wl), "wowl", &wowl);
+ if (err) {
+ WL_ERR(("Error fetching WOWL %d\n", err));
+ }
+ if (wowlan->disconnect) {
+ WL_INF(("Requesting wake on Disconnect\n"));
+ wowl |= WL_WOWL_DIS | WL_WOWL_BCN;
+ }
+ if (wowlan->magic_pkt) {
+ WL_INF(("Requesting wake on Magic Pkt\n"));
+ wowl |= WL_WOWL_MAGIC;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ if (wowlan->gtk_rekey_failure) {
+ WL_INF(("Requesting wake GTK rekey failure Pkt\n"));
+ wowl |= WL_WOWL_GTK_FAILURE;
+ }
+ if (wowlan->four_way_handshake) {
+ WL_INF(("Requesting wake on 4way handshake request\n"));
+ wowl |= WL_WOWL_M1;
+ }
+#endif
+
+ wowl |= WL_WOWL_KEYROT;
+
+ err = wl_dev_intvar_set(wl_to_ndev(wl), "wowl", wowl);
+ if (err) {
+ WL_ERR(("Error enabling WOWL %d\n", err));
+ }
+
+ return err;
+}
+#else
+static int wl_cfg80211_suspend(struct wiphy *wiphy)
+{
+ return 0;
+}
+#endif
+
+static int wl_cfg80211_resume(struct wiphy *wiphy)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ struct wl_cfg80211_priv *wl = wiphy_to_wl(wiphy);
+ wlc_rekey_info_t *rekey = (wlc_rekey_info_t *)wl->extra_buf;
+ s32 err;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ struct cfg80211_wowlan_wakeup wakeup;
+ int result;
+
+ memset(&wakeup, 0, sizeof(wakeup));
+ wakeup.pattern_idx = -1;
+
+ result = wl_wowl_ind_wake_reason(wl, &wakeup);
+ switch (result) {
+ case -1:
+ break;
+ case 0:
+ cfg80211_report_wowlan_wakeup(wl_to_wdev(wl), NULL, GFP_KERNEL);
+ break;
+ case 1:
+ cfg80211_report_wowlan_wakeup(wl_to_wdev(wl), &wakeup, GFP_KERNEL);
+ break;
+ }
+#endif
+
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "wowl_replay", (s8 *)rekey,
+ sizeof(wlc_rekey_info_t));
+ if (!err) {
+ WL_INF(("Send up replay counter %x%x%x%x%x%x%x%x\n",
+ rekey->replay_counter[0], rekey->replay_counter[1],
+ rekey->replay_counter[2], rekey->replay_counter[3],
+ rekey->replay_counter[4], rekey->replay_counter[5],
+ rekey->replay_counter[6], rekey->replay_counter[7]));
+ cfg80211_gtk_rekey_notify(wl_to_ndev(wl), (u8 *)&wl->bssid.octet,
+ rekey->replay_counter, GFP_KERNEL);
+ }
+#endif
+ return 0;
+}
+#endif
+
+static struct cfg80211_ops wl_cfg80211_ops = {
+ .change_virtual_intf = wl_cfg80211_change_iface,
+ .scan = wl_cfg80211_scan,
+ .set_wiphy_params = wl_cfg80211_set_wiphy_params,
+ .join_ibss = wl_cfg80211_join_ibss,
+ .leave_ibss = wl_cfg80211_leave_ibss,
+ .get_station = wl_cfg80211_get_station,
+ .set_tx_power = wl_cfg80211_set_tx_power,
+ .get_tx_power = wl_cfg80211_get_tx_power,
+ .add_key = wl_cfg80211_add_key,
+ .del_key = wl_cfg80211_del_key,
+ .get_key = wl_cfg80211_get_key,
+ .set_default_key = wl_cfg80211_config_default_key,
+ .set_power_mgmt = wl_cfg80211_set_power_mgmt,
+ .connect = wl_cfg80211_connect,
+ .disconnect = wl_cfg80211_disconnect,
+#ifdef CONFIG_PM
+ .suspend = wl_cfg80211_suspend,
+ .resume = wl_cfg80211_resume,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ .set_rekey_data = wl_cfg80211_rekey,
+#endif
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+ .set_pmksa = wl_cfg80211_set_pmksa,
+ .del_pmksa = wl_cfg80211_del_pmksa,
+ .flush_pmksa = wl_cfg80211_flush_pmksa
+#endif
+};
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+static const struct wiphy_wowlan_support wl_wowlan_support = {
+#else
+static struct wiphy_wowlan_support wl_wowlan_support = {
+#endif
+ .flags = WIPHY_WOWLAN_MAGIC_PKT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
+ | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | WIPHY_WOWLAN_GTK_REKEY_FAILURE |
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ
+#endif
+ | WIPHY_WOWLAN_DISCONNECT,
+};
+#endif
+#endif
+
+static s32 wl_mode_to_nl80211_iftype(s32 mode)
+{
+ s32 err = 0;
+
+ switch (mode) {
+ case WL_MODE_BSS:
+ return NL80211_IFTYPE_STATION;
+ case WL_MODE_IBSS:
+ return NL80211_IFTYPE_ADHOC;
+ default:
+ return NL80211_IFTYPE_UNSPECIFIED;
+ }
+
+ return err;
+}
+
+static s32 wl_alloc_wdev(struct device *dev, struct wireless_dev **rwdev)
+{
+ struct wireless_dev *wdev;
+ s32 err = 0;
+
+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+ if (!wdev) {
+ WL_ERR(("Could not allocate wireless device\n"));
+ err = -ENOMEM;
+ goto early_out;
+ }
+ wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_cfg80211_priv));
+ if (!wdev->wiphy) {
+ WL_ERR(("Couldn not allocate wiphy device\n"));
+ err = -ENOMEM;
+ goto wiphy_new_out;
+ }
+ set_wiphy_dev(wdev->wiphy, dev);
+ wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+#endif
+ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wdev->wiphy->cipher_suites = __wl_cipher_suites;
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+
+ wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+#endif
+
+#ifdef CONFIG_PM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+ wdev->wiphy->wowlan = &wl_wowlan_support;
+#else
+ wdev->wiphy->wowlan = wl_wowlan_support;
+#endif
+#endif
+#endif
+
+ err = wiphy_register(wdev->wiphy);
+ if (err < 0) {
+ WL_ERR(("Couldn not register wiphy device (%d)\n", err));
+ goto wiphy_register_out;
+ }
+
+ *rwdev = wdev;
+ return err;
+
+wiphy_register_out:
+ wiphy_free(wdev->wiphy);
+
+wiphy_new_out:
+ kfree(wdev);
+
+early_out:
+ *rwdev = wdev;
+ return err;
+}
+
+static void wl_free_wdev(struct wl_cfg80211_priv *wl)
+{
+ struct wireless_dev *wdev = wl_to_wdev(wl);
+
+ if (!wdev) {
+ WL_ERR(("wdev is invalid\n"));
+ return;
+ }
+ wiphy_unregister(wdev->wiphy);
+ wiphy_free(wdev->wiphy);
+ kfree(wdev);
+ wl_to_wdev(wl) = NULL;
+}
+
+static s32 wl_inform_bss(struct wl_cfg80211_priv *wl, struct wl_scan_results *bss_list)
+{
+ struct wl_bss_info *bi = NULL;
+ s32 err = 0;
+ int i;
+
+ if (bss_list->version != WL_BSS_INFO_VERSION) {
+ WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version));
+ return -EOPNOTSUPP;
+ }
+ WL_DBG(("scanned AP count (%d)\n", bss_list->count));
+ bi = next_bss(bss_list, bi);
+ for_each_bss(bss_list, bi, i) {
+ err = wl_inform_single_bss(wl, bi);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+static s32 wl_inform_single_bss(struct wl_cfg80211_priv *wl, struct wl_bss_info *bi)
+{
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_channel *channel;
+ struct wl_cfg80211_bss_info *notif_bss_info;
+ struct wl_cfg80211_scan_req *sr = wl_to_sr(wl);
+ struct beacon_proberesp *beacon_proberesp;
+ struct cfg80211_bss *cbss = NULL;
+ s32 mgmt_type;
+ u32 signal;
+ u32 freq;
+ s32 err = 0;
+ u8 *notify_ie;
+ size_t notify_ielen;
+
+ if (dtoh32(bi->length) > WL_BSS_INFO_MAX) {
+ WL_DBG(("Beacon is larger than buffer. Discarding\n"));
+ return err;
+ }
+ notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
+ WL_BSS_INFO_MAX, GFP_KERNEL);
+ if (!notif_bss_info) {
+ WL_ERR(("notif_bss_info alloc failed\n"));
+ return -ENOMEM;
+ }
+ mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
+ notif_bss_info->channel = bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
+
+ notif_bss_info->rssi = bi->RSSI;
+ memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
+ mgmt_type = wl->active_scan ? IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
+ if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
+ }
+ beacon_proberesp = wl->active_scan ? (struct beacon_proberesp *)&mgmt->u.probe_resp :
+ (struct beacon_proberesp *)&mgmt->u.beacon;
+ beacon_proberesp->timestamp = 0;
+ beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
+ beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
+ wl_rst_ie(wl);
+
+ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
+ wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
+ offsetof(struct wl_cfg80211_bss_info, frame_buf));
+ notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) +
+ wl_get_ielen(wl);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel,
+ (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ?
+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ);
+#else
+ freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+#endif
+ if (freq == 0) {
+ WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+ channel = ieee80211_get_channel(wiphy, freq);
+ if (unlikely(!channel)) {
+ WL_ERR(("ieee80211_get_channel error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+
+ WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
+ bi->SSID, notif_bss_info->rssi, notif_bss_info->channel,
+ mgmt->u.beacon.capab_info, &bi->BSSID));
+
+ signal = notif_bss_info->rssi * 100;
+ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+ le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL);
+ if (unlikely(!cbss)) {
+ WL_ERR(("cfg80211_inform_bss_frame error\n"));
+ kfree(notif_bss_info);
+ return -EINVAL;
+ }
+
+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+ notify_ielen = le32_to_cpu(bi->ie_length);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
+ cbss = cfg80211_inform_bss(wiphy, channel, (const u8 *)(bi->BSSID.octet),
+ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
+ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+#else
+ cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, (const u8 *)(bi->BSSID.octet),
+ 0, beacon_proberesp->capab_info, beacon_proberesp->beacon_int,
+ (const u8 *)notify_ie, notify_ielen, signal, GFP_KERNEL);
+#endif
+
+ if (unlikely(!cbss))
+ return -ENOMEM;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ cfg80211_put_bss(wiphy, cbss);
+#else
+ cfg80211_put_bss(cbss);
+#endif
+
+ kfree(notif_bss_info);
+
+ return err;
+}
+
+static s32
+wl_notify_connect_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 event = EVENT_TYPE(e);
+ u16 flags = EVENT_FLAGS(e);
+ u32 status = EVENT_STATUS(e);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ struct ieee80211_channel *channel = NULL;
+ struct wiphy *wiphy;
+ u32 chanspec, chan;
+ u32 freq, band;
+#endif
+
+ WL_DBG(("\n"));
+
+ if (!wl_is_ibssmode(wl)) {
+ if (event == WLC_E_LINK && (flags & WLC_EVENT_MSG_LINK)) {
+ wl_link_up(wl);
+ wl_bss_connect_done(wl, ndev, e, data, true);
+ wl->profile->active = true;
+ }
+ else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
+ event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
+ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
+#else
+ cfg80211_disconnected(ndev, 0, NULL, 0, false, GFP_KERNEL);
+#endif
+ clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_link_down(wl);
+ wl_init_prof(wl->profile);
+ }
+ else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
+ wl_bss_connect_done(wl, ndev, e, data, false);
+ }
+ else {
+ WL_DBG(("no action (BSS mode)\n"));
+ }
+ }
+ else {
+ if (event == WLC_E_JOIN) {
+ WL_DBG(("joined in IBSS network\n"));
+ }
+ if (event == WLC_E_START) {
+ WL_DBG(("started IBSS network\n"));
+ }
+ if (event == WLC_E_JOIN || event == WLC_E_START) {
+ wl_link_up(wl);
+ wl_get_assoc_ies(wl);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+ wiphy = wl_to_wiphy(wl);
+ err = wl_dev_intvar_get(ndev, "chanspec", &chanspec);
+ if (err) {
+ WL_ERR(("Could not get chanspec, err %d\n", err));
+ return err;
+ }
+ chan = wf_chspec_ctlchan(chanspec);
+ band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+ freq = ieee80211_channel_to_frequency(chan, band);
+ channel = ieee80211_get_channel(wiphy, freq);
+ cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, channel, GFP_KERNEL);
+#else
+ cfg80211_ibss_joined(ndev, (u8 *)&wl->bssid, GFP_KERNEL);
+#endif
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl->profile->active = true;
+ }
+ else if ((event == WLC_E_LINK && ~(flags & WLC_EVENT_MSG_LINK)) ||
+ event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+ clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_link_down(wl);
+ wl_init_prof(wl->profile);
+ }
+ else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
+ WL_DBG(("no action - join fail (IBSS mode)\n"));
+ }
+ else {
+ WL_DBG(("no action (IBSS mode)\n"));
+ }
+ }
+
+ return err;
+}
+
+static s32
+wl_notify_roaming_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ s32 err = 0;
+ u32 status = EVENT_STATUS(e);
+
+ WL_DBG(("\n"));
+
+ if (status == WLC_E_STATUS_SUCCESS) {
+ err = wl_bss_roaming_done(wl, ndev, e, data);
+ wl->profile->active = true;
+ }
+
+ return err;
+}
+
+static __used s32
+wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ u32 buflen;
+
+ buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ BUG_ON(!buflen);
+
+ return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
+}
+
+static s32
+wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, s32 buf_len)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(dev);
+ u32 len;
+ s32 err = 0;
+
+ len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ BUG_ON(!len);
+ err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ if (err) {
+ WL_INF(("error (%d)\n", err));
+ return err;
+ }
+ memcpy(buf, wl->ioctl_buf, buf_len);
+
+ return err;
+}
+
+static s32 wl_get_assoc_ies(struct wl_cfg80211_priv *wl)
+{
+ struct net_device *ndev = wl_to_ndev(wl);
+ struct wl_cfg80211_assoc_ielen *assoc_info;
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ u32 req_len;
+ u32 resp_len;
+ s32 err = 0;
+
+ err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc info (%d)\n", err));
+ return err;
+ }
+ assoc_info = (struct wl_cfg80211_assoc_ielen *)wl->extra_buf;
+ req_len = assoc_info->req_len;
+ resp_len = assoc_info->resp_len;
+ if (req_len) {
+ err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc req (%d)\n", err));
+ return err;
+ }
+ conn_info->req_ie_len = req_len;
+ conn_info->req_ie =
+ kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
+ } else {
+ conn_info->req_ie_len = 0;
+ conn_info->req_ie = NULL;
+ }
+ if (resp_len) {
+ err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf, WL_ASSOC_INFO_MAX);
+ if (err) {
+ WL_ERR(("could not get assoc resp (%d)\n", err));
+ return err;
+ }
+ conn_info->resp_ie_len = resp_len;
+ conn_info->resp_ie =
+ kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
+ } else {
+ conn_info->resp_ie_len = 0;
+ conn_info->resp_ie = NULL;
+ }
+ WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
+ conn_info->resp_ie_len));
+
+ return err;
+}
+
+static void wl_ch_to_chanspec(struct ieee80211_channel *chan, struct wl_join_params *join_params,
+ size_t *join_params_size)
+{
+ chanspec_t chanspec = 0;
+
+ if (chan) {
+ join_params->params.chanspec_num = 1;
+ join_params->params.chanspec_list[0] =
+ ieee80211_frequency_to_channel(chan->center_freq);
+
+ if (chan->band == IEEE80211_BAND_2GHZ) {
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ }
+ else if (chan->band == IEEE80211_BAND_5GHZ) {
+ chanspec |= WL_CHANSPEC_BAND_5G;
+ }
+ else {
+ WL_ERR(("Unknown band\n"));
+ BUG();
+ }
+
+ chanspec |= WL_CHANSPEC_BW_20;
+
+ *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+ join_params->params.chanspec_num * sizeof(chanspec_t);
+
+ join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ join_params->params.chanspec_list[0] |= chanspec;
+ join_params->params.chanspec_list[0] =
+ htodchanspec(join_params->params.chanspec_list[0]);
+
+ join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
+
+ WL_DBG(("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
+ join_params->params.chanspec_list[0],
+ join_params->params.chanspec_list[0], chanspec));
+ }
+}
+
+static s32 wl_update_bss_info(struct wl_cfg80211_priv *wl)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ struct wiphy *wiphy = wl_to_wiphy(wl);
+#endif
+ struct cfg80211_bss *bss;
+ struct wl_bss_info *bi;
+ struct wlc_ssid *ssid;
+ struct bcm_tlv *tim;
+ s32 dtim_period;
+ size_t ie_len;
+ u8 *ie;
+ s32 err = 0;
+
+ ssid = &wl->profile->ssid;
+ bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
+ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+
+ rtnl_lock();
+ if (!bss) {
+ WL_DBG(("Could not find the AP\n"));
+ *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO, wl->extra_buf,
+ WL_EXTRA_BUF_MAX);
+ if (err) {
+ WL_ERR(("Could not get bss info %d\n", err));
+ goto update_bss_info_out;
+ }
+ bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+ if (memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN)) {
+ err = -EIO;
+ goto update_bss_info_out;
+ }
+ err = wl_inform_single_bss(wl, bi);
+ if (err)
+ goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + bi->ie_offset;
+ ie_len = bi->ie_length;
+ } else {
+ WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
+ ie = (u8 *)(bss->ies->data);
+ ie_len = bss->ies->len;
+#else
+ ie = bss->information_elements;
+ ie_len = bss->len_information_elements;
+#endif
+ wl->conf->channel = *bss->channel;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+ cfg80211_put_bss(wiphy, bss);
+#else
+ cfg80211_put_bss(bss);
+#endif
+ }
+
+ tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim) {
+ dtim_period = tim->data[1];
+ } else {
+
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period));
+ if (err) {
+ WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
+ goto update_bss_info_out;
+ }
+ }
+
+update_bss_info_out:
+ rtnl_unlock();
+ return err;
+}
+
+static s32
+wl_bss_roaming_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ s32 err = 0;
+
+ wl_get_assoc_ies(wl);
+ memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+ cfg80211_roamed(ndev,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
+ &wl->conf->channel,
+#endif
+ (u8 *)&wl->bssid,
+ conn_info->req_ie, conn_info->req_ie_len,
+ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
+ WL_DBG(("Report roaming result\n"));
+
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+
+ return err;
+}
+
+static s32
+wl_bss_connect_done(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data, bool completed)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+ s32 err = 0;
+
+ if (wl->scan_request) {
+ WL_DBG(("%s: Aborting scan\n", __FUNCTION__));
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
+
+ if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+ if (completed) {
+ wl_get_assoc_ies(wl);
+ memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+ memcpy(wl->profile->bssid, &e->addr, ETHER_ADDR_LEN);
+ wl_update_bss_info(wl);
+ set_bit(WL_STATUS_CONNECTED, &wl->status);
+ }
+
+ WL_DBG(("Reporting BSS network join result \"%s\"\n",
+ wl->profile->ssid.SSID));
+ cfg80211_connect_result(ndev, (u8 *)&wl->bssid, conn_info->req_ie,
+ conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len,
+ completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL);
+ WL_DBG(("Connection %s\n", completed ? "Succeeded" : "FAILed"));
+ }
+
+ return err;
+}
+
+static s32
+wl_notify_mic_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ u16 flags = EVENT_FLAGS(e);
+ enum nl80211_key_type key_type;
+
+ WL_DBG(("\n"));
+
+ rtnl_lock();
+ if (flags & WLC_EVENT_MSG_GROUP)
+ key_type = NL80211_KEYTYPE_GROUP;
+ else
+ key_type = NL80211_KEYTYPE_PAIRWISE;
+
+ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL);
+ rtnl_unlock();
+
+ return 0;
+}
+
+static s32
+wl_notify_scan_status(struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data)
+{
+ struct channel_info channel_inform;
+ struct wl_scan_results *bss_list;
+ u32 buflen;
+ s32 err = 0;
+
+ WL_DBG(("\n"));
+
+ rtnl_lock();
+ err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, sizeof(channel_inform));
+ if (err) {
+ WL_ERR(("scan busy (%d)\n", err));
+ goto scan_done_out;
+ }
+ channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+ if (channel_inform.scan_channel) {
+
+ WL_DBG(("channel_inform.scan_channel (%d)\n", channel_inform.scan_channel));
+ }
+
+ for (buflen = WL_SCAN_BUF_BASE; ; ) {
+ bss_list = (struct wl_scan_results *) kmalloc(buflen, GFP_KERNEL);
+ if (!bss_list) {
+ WL_ERR(("%s Out of memory for scan results, (%d)\n", ndev->name, err));
+ goto scan_done_out;
+ }
+ memset(bss_list, 0, buflen);
+ bss_list->buflen = htod32(buflen);
+ err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, buflen);
+ if (!err) {
+ break;
+ }
+ else if (err == -E2BIG) {
+ kfree(bss_list);
+ buflen *= 2;
+ }
+ else {
+ WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
+ kfree(bss_list);
+ err = -EINVAL;
+ goto scan_done_out;
+ }
+ }
+
+ bss_list->buflen = dtoh32(bss_list->buflen);
+ bss_list->version = dtoh32(bss_list->version);
+ bss_list->count = dtoh32(bss_list->count);
+
+ err = wl_inform_bss(wl, bss_list);
+ kfree(bss_list);
+
+scan_done_out:
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, false);
+ wl->scan_request = NULL;
+ }
+ rtnl_unlock();
+ return err;
+}
+
+static void wl_init_conf(struct wl_cfg80211_conf *conf)
+{
+ conf->mode = (u32)-1;
+ conf->frag_threshold = (u32)-1;
+ conf->rts_threshold = (u32)-1;
+ conf->retry_short = (u32)-1;
+ conf->retry_long = (u32)-1;
+ conf->tx_power = -1;
+}
+
+static void wl_init_prof(struct wl_cfg80211_profile *prof)
+{
+ memset(prof, 0, sizeof(*prof));
+}
+
+static void wl_init_eloop_handler(struct wl_cfg80211_event_loop *el)
+{
+ memset(el, 0, sizeof(*el));
+ el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
+ el->handler[WLC_E_JOIN] = wl_notify_connect_status;
+ el->handler[WLC_E_START] = wl_notify_connect_status;
+ el->handler[WLC_E_LINK] = wl_notify_connect_status;
+ el->handler[WLC_E_NDIS_LINK] = wl_notify_connect_status;
+ el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
+ el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
+ el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+ el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
+ el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
+}
+
+static s32 wl_init_priv_mem(struct wl_cfg80211_priv *wl)
+{
+ wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
+ if (!wl->conf) {
+ WL_ERR(("wl_cfg80211_conf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
+ if (!wl->profile) {
+ WL_ERR(("wl_cfg80211_profile alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
+ if (!wl->scan_req_int) {
+ WL_ERR(("Scan req alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+ if (!wl->ioctl_buf) {
+ WL_ERR(("Ioctl buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+ wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+ if (!wl->extra_buf) {
+ WL_ERR(("Extra buf alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+
+ wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
+ if (!wl->pmk_list) {
+ WL_ERR(("pmk list alloc failed\n"));
+ goto init_priv_mem_out;
+ }
+
+ return 0;
+
+init_priv_mem_out:
+ wl_deinit_priv_mem(wl);
+
+ return -ENOMEM;
+}
+
+static void wl_deinit_priv_mem(struct wl_cfg80211_priv *wl)
+{
+ kfree(wl->conf);
+ wl->conf = NULL;
+ kfree(wl->profile);
+ wl->profile = NULL;
+ kfree(wl->scan_req_int);
+ wl->scan_req_int = NULL;
+ kfree(wl->ioctl_buf);
+ wl->ioctl_buf = NULL;
+ kfree(wl->extra_buf);
+ wl->extra_buf = NULL;
+ kfree(wl->pmk_list);
+ wl->pmk_list = NULL;
+}
+
+static s32 wl_create_event_handler(struct wl_cfg80211_priv *wl)
+{
+ sema_init(&wl->event_sync, 0);
+ wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
+ if (IS_ERR(wl->event_tsk)) {
+ wl->event_tsk = NULL;
+ WL_ERR(("failed to create event thread\n"));
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void wl_destroy_event_handler(struct wl_cfg80211_priv *wl)
+{
+ if (wl->event_tsk) {
+ send_sig(SIGTERM, wl->event_tsk, 1);
+ kthread_stop(wl->event_tsk);
+ wl->event_tsk = NULL;
+ }
+}
+
+static s32 wl_init_cfg80211_priv(struct wl_cfg80211_priv *wl, struct wireless_dev *wdev)
+{
+ s32 err = 0;
+
+ wl->wdev = wdev;
+
+ wl->scan_request = NULL;
+ wl->active_scan = true;
+ wl_init_eq(wl);
+ err = wl_init_priv_mem(wl);
+ if (err)
+ return err;
+
+ if (wl_create_event_handler(wl))
+ return -ENOMEM;
+
+ wl_init_eloop_handler(&wl->el);
+
+ if (err)
+ return err;
+
+ wl_init_conf(wl->conf);
+ wl_init_prof(wl->profile);
+ wl_link_down(wl);
+
+ return err;
+}
+
+static void wl_deinit_cfg80211_priv(struct wl_cfg80211_priv *wl)
+{
+ wl_destroy_event_handler(wl);
+ wl_flush_eq(wl);
+ wl_link_down(wl);
+ wl_deinit_priv_mem(wl);
+}
+
+s32 wl_cfg80211_attach(struct net_device *ndev, struct device *dev, int passive)
+{
+ struct wireless_dev *wdev;
+ struct wl_cfg80211_priv *wl;
+ s32 err = 0;
+
+ if (!ndev) {
+ WL_ERR(("ndev is invaild\n"));
+ return -ENODEV;
+ }
+
+ err = wl_alloc_wdev(dev, &wdev);
+ if (err < 0) {
+ return err;
+ }
+
+ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+ wl = wdev_to_wl(wdev);
+ ndev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+ wdev->netdev = ndev;
+ err = wl_init_cfg80211_priv(wl, wdev);
+ if (err) {
+ WL_ERR(("Failed to init iwm_priv (%d)\n", err));
+ goto cfg80211_attach_out;
+ }
+ wl->passive = !!passive;
+
+ if (!err) {
+ WL_INF(("Registered CFG80211 phy\n"));
+ }
+ return err;
+
+cfg80211_attach_out:
+ wl_free_wdev(wl);
+ return err;
+}
+
+void wl_cfg80211_detach(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl;
+
+ if (ndev->ieee80211_ptr == NULL) {
+ WL_ERR(( "NULL ndev->ieee80211ptr, unable to deref wl\n"));
+ return;
+ }
+ wl = ndev_to_wl(ndev);
+
+ wl_deinit_cfg80211_priv(wl);
+ wl_free_wdev(wl);
+}
+
+static void wl_wakeup_event(struct wl_cfg80211_priv *wl)
+{
+ up(&wl->event_sync);
+}
+
+static s32 wl_event_handler(void *data)
+{
+ struct wl_cfg80211_priv *wl = (struct wl_cfg80211_priv *)data;
+ struct wl_cfg80211_event_q *e;
+
+ allow_signal(SIGTERM);
+ while (!down_interruptible(&wl->event_sync)) {
+ if (kthread_should_stop())
+ break;
+ e = wl_deq_event(wl);
+ if (!e) {
+ WL_ERR(("eqeue empty..\n"));
+ BUG();
+ }
+ if (wl->el.handler[e->etype]) {
+ WL_DBG(("event type (%d)\n", e->etype));
+ wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg, e->edata);
+ } else {
+ WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
+ }
+ wl_put_event(e);
+ }
+ WL_DBG(("%s was terminated\n", __func__));
+ return 0;
+}
+
+void
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+{
+
+ u32 event_type = EVENT_TYPE(e);
+
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+#if defined(WL_DBGMSG_ENABLE)
+ s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
+ wl_dbg_estr[event_type] : (s8 *) "Unknown";
+ WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
+#endif
+ if (!wl_enq_event(wl, event_type, e, data))
+ wl_wakeup_event(wl);
+}
+
+static void wl_init_eq(struct wl_cfg80211_priv *wl)
+{
+ wl_init_eq_lock(wl);
+ INIT_LIST_HEAD(&wl->eq_list);
+}
+
+static void wl_flush_eq(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_event_q *e;
+
+ wl_lock_eq(wl);
+ while (!list_empty(&wl->eq_list)) {
+ e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
+ list_del(&e->eq_list);
+ kfree(e);
+ }
+ wl_unlock_eq(wl);
+}
+
+static struct wl_cfg80211_event_q *wl_deq_event(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_event_q *e = NULL;
+
+ wl_lock_eq(wl);
+ if (!list_empty(&wl->eq_list)) {
+ e = list_first_entry(&wl->eq_list, struct wl_cfg80211_event_q, eq_list);
+ list_del(&e->eq_list);
+ }
+ wl_unlock_eq(wl);
+
+ return e;
+}
+
+static s32
+wl_enq_event(struct wl_cfg80211_priv *wl, u32 event, const wl_event_msg_t *msg, void *data)
+{
+ struct wl_cfg80211_event_q *e;
+ s32 err = 0;
+
+ e = kzalloc(sizeof(struct wl_cfg80211_event_q), GFP_ATOMIC);
+ if (!e) {
+ WL_ERR(("event alloc failed\n"));
+ return -ENOMEM;
+ }
+
+ e->etype = event;
+ memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
+ if (data) {
+ }
+
+ spin_lock(&wl->eq_lock);
+ list_add_tail(&e->eq_list, &wl->eq_list);
+ spin_unlock(&wl->eq_lock);
+
+ return err;
+}
+
+static void wl_put_event(struct wl_cfg80211_event_q *e)
+{
+ kfree(e);
+}
+
+static s32 wl_set_mode(struct net_device *ndev, s32 iftype)
+{
+ s32 infra = 0;
+ s32 ap = 0;
+ s32 err = 0;
+
+ switch (iftype) {
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ WL_ERR(("type (%d) : currently we do not support this mode\n",
+ iftype));
+ err = -EINVAL;
+ return err;
+ case NL80211_IFTYPE_ADHOC:
+ break;
+ case NL80211_IFTYPE_STATION:
+ infra = 1;
+ break;
+ default:
+ err = -EINVAL;
+ WL_ERR(("invalid type (%d)\n", iftype));
+ return err;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+ WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
+ err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+ if (err) {
+ WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
+ return err;
+ }
+ err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
+ if (err) {
+ WL_ERR(("WLC_SET_AP error (%d)\n", err));
+ return err;
+ }
+
+ return 0;
+}
+
+static void wl_update_wowl(struct net_device *ndev)
+{
+#ifdef CONFIG_PM
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
+ s32 offloads = 0;
+ s32 err = 0;
+ err = wl_dev_bufvar_get(wl_to_ndev(wl), "offloads",
+ (s8 *)&offloads, sizeof(offloads));
+ if (err == 0 && offloads == 1) {
+ WL_INF(("Supports offloads\n"));
+ wl->offloads = true;
+ } else {
+ WL_INF(("No offloads supported\n"));
+ wl->offloads = false;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
+ wdev->wiphy->wowlan = NULL;
+#else
+ memset(&wdev->wiphy->wowlan, 0, sizeof(struct wiphy_wowlan_support));
+#endif
+#endif
+ }
+#endif
+}
+
+static s32 wl_update_wiphybands(struct wl_cfg80211_priv *wl)
+{
+ struct wiphy *wiphy;
+ s32 phy_list;
+ s8 phy;
+ s32 err = 0;
+
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list, sizeof(phy_list));
+ if (err) {
+ WL_ERR(("error (%d)\n", err));
+ return err;
+ }
+
+ phy = ((char *)&phy_list)[0];
+ WL_DBG(("%c phy\n", phy));
+
+ if (phy == 'n' || phy == 'a' || phy == 'v') {
+ wiphy = wl_to_wiphy(wl);
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
+ }
+
+ return err;
+}
+
+s32 wl_cfg80211_up(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ s32 err = 0;
+ struct wireless_dev *wdev = ndev->ieee80211_ptr;
+
+ wl_set_mode(ndev, wdev->iftype);
+ err = wl_update_wiphybands(wl);
+ if (err) {
+ return err;
+ }
+
+ wl_update_wowl(ndev);
+ return 0;
+}
+
+s32 wl_cfg80211_down(struct net_device *ndev)
+{
+ struct wl_cfg80211_priv *wl = ndev_to_wl(ndev);
+ s32 err = 0;
+
+ if (wl->scan_request) {
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
+
+ return err;
+}
+
+static bool wl_is_ibssmode(struct wl_cfg80211_priv *wl)
+{
+ return wl->conf->mode == WL_MODE_IBSS;
+}
+
+static void wl_rst_ie(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+
+ ie->offset = 0;
+}
+
+static __used s32 wl_add_ie(struct wl_cfg80211_priv *wl, u8 t, u8 l, u8 *v)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
+ WL_ERR(("ei crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ ie->buf[ie->offset] = t;
+ ie->buf[ie->offset + 1] = l;
+ memcpy(&ie->buf[ie->offset + 2], v, l);
+ ie->offset += l + 2;
+
+ return err;
+}
+
+static s32 wl_mrg_ie(struct wl_cfg80211_priv *wl, u8 *ie_stream, u16 ie_size)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset + ie_size > WL_TLV_INFO_MAX) {
+ WL_ERR(("ei_stream crosses buffer boundary\n"));
+ return -ENOSPC;
+ }
+ memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
+ ie->offset += ie_size;
+
+ return err;
+}
+
+static s32 wl_cp_ie(struct wl_cfg80211_priv *wl, u8 *dst, u16 dst_size)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+ s32 err = 0;
+
+ if (ie->offset > dst_size) {
+ WL_ERR(("dst_size is not enough\n"));
+ return -ENOSPC;
+ }
+ memcpy(dst, &ie->buf[0], ie->offset);
+
+ return err;
+}
+
+static u32 wl_get_ielen(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_ie *ie = wl_to_ie(wl);
+
+ return ie->offset;
+}
+
+static void wl_link_up(struct wl_cfg80211_priv *wl)
+{
+ WL_DBG(("\n"));
+}
+
+static void wl_link_down(struct wl_cfg80211_priv *wl)
+{
+ struct wl_cfg80211_connect_info *conn_info = wl_to_conn(wl);
+
+ WL_DBG(("\n"));
+
+ kfree(conn_info->req_ie);
+ conn_info->req_ie = NULL;
+ conn_info->req_ie_len = 0;
+ kfree(conn_info->resp_ie);
+ conn_info->resp_ie = NULL;
+ conn_info->resp_ie_len = 0;
+}
+
+static void wl_lock_eq(struct wl_cfg80211_priv *wl)
+{
+ spin_lock_irq(&wl->eq_lock);
+}
+
+static void wl_unlock_eq(struct wl_cfg80211_priv *wl)
+{
+ spin_unlock_irq(&wl->eq_lock);
+}
+
+static void wl_init_eq_lock(struct wl_cfg80211_priv *wl)
+{
+ spin_lock_init(&wl->eq_lock);
+}
+
+#endif
diff --git a/src/wl/sys/wl_cfg80211_hybrid.h b/src/wl/sys/wl_cfg80211_hybrid.h
new file mode 100644
index 0000000..bc6f3ad
--- /dev/null
+++ b/src/wl/sys/wl_cfg80211_hybrid.h
@@ -0,0 +1,231 @@
+/*
+ * Linux-specific portion of Broadcom 802.11abg Networking Device Driver
+ * cfg80211 interface
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_cfg80211.h,v 1.1.8.1 2011-01-26 00:57:46 $
+ */
+
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
+
+#include <net/cfg80211.h>
+#include <wlioctl.h>
+
+struct wl_cfg80211_conf;
+struct wl_cfg80211_priv;
+struct wl_cfg80211_security;
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+
+#define WL_DBGMSG_ENABLE
+
+#define WL_DBG_NONE 0
+#define WL_DBG_DBG (1 << 2)
+#define WL_DBG_INFO (1 << 1)
+#define WL_DBG_ERR (1 << 0)
+#define WL_DBG_MASK ((WL_DBG_DBG | WL_DBG_INFO | WL_DBG_ERR) << 1)
+
+#if defined(WL_DBGMSG_ENABLE)
+#define WL_DBG(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_DBG) { \
+ printk(KERN_ERR "DEBUG @%s :", __func__); \
+ printk args; \
+ } \
+} while (0)
+#else
+#define WL_DBG(args)
+#endif
+
+#define WL_ERR(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_ERR) { \
+ if (net_ratelimit()) { \
+ printk(KERN_ERR "ERROR @%s : ", __func__); \
+ printk args; \
+ } \
+ } \
+} while (0)
+
+#define WL_INF(args) \
+do { \
+ if (wl_dbg_level & WL_DBG_INFO) { \
+ if (net_ratelimit()) { \
+ printk(KERN_ERR "INFO @%s : ", __func__); \
+ printk args; \
+ } \
+ } \
+} while (0)
+
+#define WL_NUM_SCAN_MAX 1
+#define WL_NUM_PMKIDS_MAX MAXPMKID
+#define WL_SCAN_BUF_BASE (16*1024)
+#define WL_TLV_INFO_MAX 1024
+#define WL_BSS_INFO_MAX 2048
+#define WL_ASSOC_INFO_MAX 512
+#define WL_IOCTL_LEN_MAX 2048
+#define WL_EXTRA_BUF_MAX 2048
+#define WL_AP_MAX 256
+
+enum wl_cfg80211_status {
+ WL_STATUS_CONNECTING,
+ WL_STATUS_CONNECTED
+};
+
+enum wl_cfg80211_mode {
+ WL_MODE_BSS,
+ WL_MODE_IBSS,
+ WL_MODE_AP
+};
+
+struct beacon_proberesp {
+ __le64 timestamp;
+ __le16 beacon_int;
+ __le16 capab_info;
+ u8 variable[0];
+} __attribute__ ((packed));
+
+struct wl_cfg80211_conf {
+ u32 mode;
+ u32 frag_threshold;
+ u32 rts_threshold;
+ u32 retry_short;
+ u32 retry_long;
+ s32 tx_power;
+ struct ieee80211_channel channel;
+};
+
+struct wl_cfg80211_event_loop {
+ s32(*handler[WLC_E_LAST]) (struct wl_cfg80211_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void *data);
+};
+
+struct wl_cfg80211_bss_info {
+ u16 band;
+ u16 channel;
+ s16 rssi;
+ u16 frame_len;
+ u8 frame_buf[1];
+};
+
+struct wl_cfg80211_scan_req {
+ struct wlc_ssid ssid;
+};
+
+struct wl_cfg80211_ie {
+ u16 offset;
+ u8 buf[WL_TLV_INFO_MAX];
+};
+
+struct wl_cfg80211_event_q {
+ struct list_head eq_list;
+ u32 etype;
+ wl_event_msg_t emsg;
+ s8 edata[1];
+};
+
+struct wl_cfg80211_security {
+ u32 wpa_versions;
+ u32 auth_type;
+ u32 cipher_pairwise;
+ u32 cipher_group;
+ u32 wpa_auth;
+};
+
+struct wl_cfg80211_profile {
+ struct wlc_ssid ssid;
+ u8 bssid[ETHER_ADDR_LEN];
+ struct wl_cfg80211_security sec;
+ bool active;
+};
+
+struct wl_cfg80211_connect_info {
+ u8 *req_ie;
+ s32 req_ie_len;
+ u8 *resp_ie;
+ s32 resp_ie_len;
+};
+
+struct wl_cfg80211_assoc_ielen {
+ u32 req_len;
+ u32 resp_len;
+};
+
+struct wl_cfg80211_pmk_list {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID - 1];
+};
+
+struct wl_cfg80211_priv {
+ struct wireless_dev *wdev;
+ struct wl_cfg80211_conf *conf;
+ struct cfg80211_scan_request *scan_request;
+ struct wl_cfg80211_event_loop el;
+ struct list_head eq_list;
+ spinlock_t eq_lock;
+ struct wl_cfg80211_scan_req *scan_req_int;
+ struct wl_cfg80211_ie ie;
+ struct ether_addr bssid;
+ struct semaphore event_sync;
+ struct wl_cfg80211_profile *profile;
+ struct wl_cfg80211_connect_info conn_info;
+ struct wl_cfg80211_pmk_list *pmk_list;
+ struct task_struct *event_tsk;
+ unsigned long status;
+ bool active_scan;
+ bool passive;
+ bool offloads;
+ u8 *ioctl_buf;
+ u8 *extra_buf;
+ u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
+};
+
+#define wl_to_dev(w) (wiphy_dev(wl->wdev->wiphy))
+#define wl_to_wiphy(w) (w->wdev->wiphy)
+#define wiphy_to_wl(w) ((struct wl_cfg80211_priv *)(wiphy_priv(w)))
+#define wl_to_wdev(w) (w->wdev)
+#define wdev_to_wl(w) ((struct wl_cfg80211_priv *)(wdev_priv(w)))
+#define wl_to_ndev(w) (w->wdev->netdev)
+#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
+#define wl_to_sr(w) (w->scan_req_int)
+#define wl_to_ie(w) (&w->ie)
+#define wl_to_conn(w) (&w->conn_info)
+
+static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
+{
+ return bss = bss ? (struct wl_bss_info *)((unsigned long)bss +
+ dtoh32(bss->length)) : list->bss_info;
+}
+
+#define for_each_bss(list, bss, __i) \
+ for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
+
+extern s32 wl_cfg80211_attach(struct net_device *ndev, struct device *dev, int flags);
+extern void wl_cfg80211_detach(struct net_device *ndev);
+
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data);
+extern s32 wl_cfg80211_up(struct net_device *ndev);
+extern s32 wl_cfg80211_down(struct net_device *ndev);
+
+#endif
diff --git a/src/wl/sys/wl_dbg.h b/src/wl/sys/wl_dbg.h
new file mode 100644
index 0000000..dc8bf26
--- /dev/null
+++ b/src/wl/sys/wl_dbg.h
@@ -0,0 +1,74 @@
+/*
+ * Minimal debug/trace/assert driver definitions for
+ * Broadcom 802.11 Networking Adapter.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_dbg.h 405851 2013-06-05 00:56:21Z $
+ */
+
+#ifndef _wl_dbg_h_
+#define _wl_dbg_h_
+
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+
+#if defined(BCMDBG) && !defined(BCMDBG_EXCLUDE_HW_TIMESTAMP)
+extern char* wlc_dbg_get_hw_timestamp(void);
+
+#define WL_TIMESTAMP() do { if (wl_msg_level2 & WL_TIMESTAMP_VAL) {\
+ printf(wlc_dbg_get_hw_timestamp()); }\
+ } while (0)
+#else
+#define WL_TIMESTAMP()
+#endif
+
+#if 0 && (VERSION_MAJOR > 9)
+extern int osl_printf(const char *fmt, ...);
+#include <IOKit/apple80211/IO8Log.h>
+#define WL_PRINT(args) do { osl_printf args; } while (0)
+#define RELEASE_PRINT(args) do { WL_PRINT(args); IO8Log args; } while (0)
+#else
+#define WL_PRINT(args) do { WL_TIMESTAMP(); printf args; } while (0)
+#endif
+
+#ifdef BCMDBG
+
+#define WL_NONE(args) do {if (wl_msg_level & 0) WL_PRINT(args);} while (0)
+
+#define WL_ERROR(args) do {if (wl_msg_level & WL_ERROR_VAL) WL_PRINT(args);} while (0)
+#define WL_TRACE(args) do {if (wl_msg_level & WL_TRACE_VAL) WL_PRINT(args);} while (0)
+
+#else
+
+#define WL_NONE(args)
+
+#ifdef BCMDBG_ERR
+#define WL_ERROR(args) WL_PRINT(args)
+#else
+#define WL_ERROR(args)
+#endif
+#define WL_TRACE(args)
+#define WL_APSTA_UPDN(args)
+#define WL_APSTA_RX(args)
+#define WL_WSEC(args)
+#define WL_WSEC_DUMP(args)
+#define WL_PCIE(args) do {if (wl_msg_level2 & WL_PCIE_VAL) WL_PRINT(args);} while (0)
+#define WL_PCIE_ON() (wl_msg_level2 & WL_PCIE_VAL)
+#endif
+
+extern uint32 wl_msg_level;
+extern uint32 wl_msg_level2;
+#endif
diff --git a/src/wl/sys/wl_export.h b/src/wl/sys/wl_export.h
new file mode 100644
index 0000000..41d4251
--- /dev/null
+++ b/src/wl/sys/wl_export.h
@@ -0,0 +1,81 @@
+/*
+ * Required functions exported by the port-specific (os-dependent) driver
+ * to common (os-independent) driver code.
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_export.h 579954 2015-08-17 18:08:53Z $
+ */
+
+#ifndef _wl_export_h_
+#define _wl_export_h_
+
+struct wl_info;
+struct wl_if;
+struct wlc_if;
+extern void wl_init(struct wl_info *wl);
+extern uint wl_reset(struct wl_info *wl);
+extern void wl_intrson(struct wl_info *wl);
+extern uint32 wl_intrsoff(struct wl_info *wl);
+extern void wl_intrsrestore(struct wl_info *wl, uint32 macintmask);
+extern void wl_event(struct wl_info *wl, char *ifname, wlc_event_t *e);
+extern void wl_event_sync(struct wl_info *wl, char *ifname, wlc_event_t *e);
+extern void wl_event_sendup(struct wl_info *wl, const wlc_event_t *e, uint8 *data, uint32 len);
+extern int wl_up(struct wl_info *wl);
+extern void wl_down(struct wl_info *wl);
+extern void wl_dump_ver(struct wl_info *wl, struct bcmstrbuf *b);
+extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state, int prio);
+extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
+extern void wl_reclaim(void);
+extern void wl_nocard_timer(void *arg);
+extern void wl_recover_nocard(struct wl_info *wl);
+extern void wl_devicerecovery(struct wl_info *wl );
+
+extern uint32 wl_pcie_bar1(struct wl_info *wl, uchar** addr);
+
+struct wl_timer;
+extern struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn)(void* arg), void *arg,
+ const char *name);
+extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
+extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms, int periodic);
+extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
+
+extern void wl_sendup(struct wl_info *wl, struct wl_if *wlif, void *p, int numpkt);
+extern char *wl_ifname(struct wl_info *wl, struct wl_if *wlif);
+extern struct wl_if *wl_add_if(struct wl_info *wl, struct wlc_if* wlcif, uint unit,
+ struct ether_addr *remote);
+extern void wl_del_if(struct wl_info *wl, struct wl_if *wlif);
+#ifdef DWDS
+extern void wl_dwds_del_if(struct wl_info *wl, struct wl_if *wlif, bool force);
+#endif
+
+extern int wl_osl_pcie_rc(struct wl_info *wl, uint op, int param);
+
+extern void wl_monitor(struct wl_info *wl, wl_rxsts_t *rxsts, void *p);
+extern void wl_set_monitor(struct wl_info *wl, int val);
+
+extern uint wl_buf_to_pktcopy(osl_t *osh, void *p, uchar *buf, int len, uint offset);
+extern void * wl_get_pktbuffer(osl_t *osh, int len);
+extern int wl_set_pktlen(osl_t *osh, void *p, int len);
+
+#define IFCTX_ARPI (1)
+#define IFCTX_NDI (2)
+#define IFCTX_NETDEV (3)
+extern void *wl_get_ifctx(struct wl_info *wl, int ctx_id, wl_if_t *wlif);
+
+#define wl_sort_bsslist(a, b) FALSE
+
+#define wl_outputpacket_complete(a, b, c) do { } while (0)
+#endif
diff --git a/src/wl/sys/wl_iw.c b/src/wl/sys/wl_iw.c
new file mode 100644
index 0000000..c4c610b
--- /dev/null
+++ b/src/wl/sys/wl_iw.c
@@ -0,0 +1,2830 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_iw.c 458427 2014-02-26 23:12:38Z $
+ */
+
+#if defined(USE_IW)
+#define LINUX_PORT
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+typedef const struct si_pub si_t;
+#include <wlioctl.h>
+
+#include <wl_dbg.h>
+#include <wl_iw.h>
+
+extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
+ uint32 reason, char* stringBuf, uint buflen);
+
+#define MAX_WLIW_IOCTL_LEN 1024
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+
+extern struct iw_statistics *wl_get_wireless_stats(struct net_device *dev);
+
+#if WIRELESS_EXT < 19
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+#endif
+
+typedef struct priv_link {
+ wl_iw_t *wliw;
+} priv_link_t;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+#define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv)
+#else
+#define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev)
+#endif
+
+#define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw)
+
+static void swap_key_from_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = htod32(key->index);
+ key->len = htod32(key->len);
+ key->algo = htod32(key->algo);
+ key->flags = htod32(key->flags);
+ key->rxiv.hi = htod32(key->rxiv.hi);
+ key->rxiv.lo = htod16(key->rxiv.lo);
+ key->iv_initialized = htod32(key->iv_initialized);
+}
+
+static void swap_key_to_BE(
+ wl_wsec_key_t *key
+)
+{
+ key->index = dtoh32(key->index);
+ key->len = dtoh32(key->len);
+ key->algo = dtoh32(key->algo);
+ key->flags = dtoh32(key->flags);
+ key->rxiv.hi = dtoh32(key->rxiv.hi);
+ key->rxiv.lo = dtoh16(key->rxiv.lo);
+ key->iv_initialized = dtoh32(key->iv_initialized);
+}
+
+static int
+dev_wlc_ioctl(
+ struct net_device *dev,
+ int cmd,
+ void *arg,
+ int len
+)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+ mm_segment_t fs;
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+ fs = get_fs();
+ set_fs(get_ds());
+#if defined(WL_USE_NETDEV_OPS)
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
+ return ret;
+}
+
+static int
+dev_wlc_intvar_set(
+ struct net_device *dev,
+ char *name,
+ int val)
+{
+ char buf[WLC_IOCTL_SMLEN];
+ uint len;
+
+ val = htod32(val);
+ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+ ASSERT(len);
+
+ return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
+}
+
+#if WIRELESS_EXT > 17
+static int
+dev_wlc_bufvar_set(
+ struct net_device *dev,
+ char *name,
+ char *buf, int len)
+{
+ char *ioctlbuf;
+ uint buflen;
+ int error;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+
+ buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(buflen);
+ error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
+
+ kfree(ioctlbuf);
+ return error;
+}
+#endif
+
+static int
+dev_wlc_bufvar_get(
+ struct net_device *dev,
+ char *name,
+ char *buf, int buflen)
+{
+ char *ioctlbuf;
+ int error;
+
+ uint len;
+
+ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
+ if (!ioctlbuf)
+ return -ENOMEM;
+ len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ ASSERT(len);
+ BCM_REFERENCE(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
+ if (!error)
+ bcopy(ioctlbuf, buf, buflen);
+
+ kfree(ioctlbuf);
+ return (error);
+}
+
+static int
+dev_wlc_intvar_get(
+ struct net_device *dev,
+ char *name,
+ int *retval)
+{
+ union {
+ char buf[WLC_IOCTL_SMLEN];
+ int val;
+ } var;
+ int error;
+
+ uint len;
+ uint data_null;
+
+ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
+ ASSERT(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
+
+ *retval = dtoh32(var.val);
+
+ return (error);
+}
+
+#if WIRELESS_EXT < 13
+struct iw_request_info
+{
+ __u16 cmd;
+ __u16 flags;
+};
+
+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
+ void *wrqu, char *extra);
+#endif
+
+#if WIRELESS_EXT > 12
+static int
+wl_iw_set_leddc(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int dc = *(int *)extra;
+ int error;
+
+ error = dev_wlc_intvar_set(dev, "leddc", dc);
+ return error;
+}
+
+static int
+wl_iw_set_vlanmode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int mode = *(int *)extra;
+ int error;
+
+ mode = htod32(mode);
+ error = dev_wlc_intvar_set(dev, "vlan_mode", mode);
+ return error;
+}
+
+static int
+wl_iw_set_pm(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int pm = *(int *)extra;
+ int error;
+
+ pm = htod32(pm);
+ error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+ return error;
+}
+#endif
+
+int
+wl_iw_send_priv_event(
+ struct net_device *dev,
+ char *flag
+)
+{
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd;
+
+ cmd = IWEVCUSTOM;
+ memset(&wrqu, 0, sizeof(wrqu));
+ if (strlen(flag) > sizeof(extra))
+ return -1;
+
+ strcpy(extra, flag);
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
+
+ return 0;
+}
+
+static int
+wl_iw_config_commit(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ void *zwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+ struct sockaddr bssid;
+
+ WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
+ return error;
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ if (!ssid.SSID_len)
+ return 0;
+
+ bzero(&bssid, sizeof(struct sockaddr));
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_name(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *cwrq,
+ char *extra
+)
+{
+ int phytype, err;
+ uint band[3];
+ char cap[5];
+
+ WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
+
+ cap[0] = 0;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0)
+ goto done;
+ if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0)
+ goto done;
+
+ band[0] = dtoh32(band[0]);
+ switch (phytype) {
+ case WLC_PHY_TYPE_A:
+ strcpy(cap, "a");
+ break;
+ case WLC_PHY_TYPE_B:
+ strcpy(cap, "b");
+ break;
+ case WLC_PHY_TYPE_LP:
+ case WLC_PHY_TYPE_G:
+ if (band[0] >= 2)
+ strcpy(cap, "abg");
+ else
+ strcpy(cap, "bg");
+ break;
+ case WLC_PHY_TYPE_N:
+ if (band[0] >= 2)
+ strcpy(cap, "abgn");
+ else
+ strcpy(cap, "bgn");
+ break;
+ }
+done:
+ snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap);
+ return 0;
+}
+
+static int
+wl_iw_set_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ int error, chan;
+ uint sf = 0;
+
+ WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
+
+ if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
+ chan = fwrq->m;
+ }
+
+ else {
+
+ if (fwrq->e >= 6) {
+ fwrq->e -= 6;
+ while (fwrq->e--)
+ fwrq->m *= 10;
+ } else if (fwrq->e < 6) {
+ while (fwrq->e++ < 6)
+ fwrq->m /= 10;
+ }
+
+ if (fwrq->m > 4000 && fwrq->m < 5000)
+ sf = WF_CHAN_FACTOR_4_G;
+
+ chan = wf_mhz2channel(fwrq->m, sf);
+ }
+ chan = htod32(chan);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
+ return error;
+
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_freq(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+
+ fwrq->m = dtoh32(ci.hw_channel);
+ fwrq->e = dtoh32(0);
+ return 0;
+}
+
+static int
+wl_iw_set_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int infra = 0, ap = 0, error = 0;
+
+ WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
+
+ switch (*uwrq) {
+ case IW_MODE_MASTER:
+ infra = ap = 1;
+ break;
+ case IW_MODE_ADHOC:
+ case IW_MODE_AUTO:
+ break;
+ case IW_MODE_INFRA:
+ infra = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ infra = htod32(infra);
+ ap = htod32(ap);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
+ return error;
+
+ return -EINPROGRESS;
+}
+
+static int
+wl_iw_get_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra
+)
+{
+ int error, infra = 0, ap = 0;
+
+ WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
+ return error;
+
+ infra = dtoh32(infra);
+ ap = dtoh32(ap);
+ *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
+
+ return 0;
+}
+
+static int
+wl_iw_get_range(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ static int channels[MAXCHANNEL+1];
+ wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+ wl_rateset_t rateset;
+ int error, i, k;
+ uint sf, ch;
+
+ int phytype;
+ int bw_cap = 0, sgi_tx = 0, nmode = 0;
+ channel_info_t ci;
+ uint8 nrate_list2copy = 0;
+ uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
+ {14, 29, 43, 58, 87, 116, 130, 144},
+ {27, 54, 81, 108, 162, 216, 243, 270},
+ {30, 60, 90, 120, 180, 240, 270, 300}};
+
+ WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(*range));
+
+ range->min_nwid = range->max_nwid = 0;
+
+ list->count = htod32(MAXCHANNEL);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+ return error;
+ for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
+ range->freq[i].i = dtoh32(list->element[i]);
+
+ ch = dtoh32(list->element[i]);
+ if (ch <= CH_MAX_2G_CHANNEL)
+ sf = WF_CHAN_FACTOR_2_4_G;
+ else
+ sf = WF_CHAN_FACTOR_5_G;
+
+ range->freq[i].m = wf_channel2mhz(ch, sf);
+ range->freq[i].e = 6;
+ }
+ range->num_frequency = range->num_channels = i;
+
+ range->max_qual.qual = 5;
+
+ range->max_qual.level = 0x100 - 200;
+
+ range->max_qual.noise = 0x100 - 200;
+
+ range->sensitivity = 65535;
+
+#if WIRELESS_EXT > 11
+
+ range->avg_qual.qual = 3;
+
+ range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
+
+ range->avg_qual.noise = 0x100 - 75;
+#endif
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ rateset.count = dtoh32(rateset.count);
+ range->num_bitrates = rateset.count;
+ for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
+ range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
+ dev_wlc_intvar_get(dev, "nmode", &nmode);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))))
+ return error;
+
+ if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) ||
+ (phytype == WLC_PHY_TYPE_LCN40))) {
+ dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
+ dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
+ dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
+ ci.hw_channel = dtoh32(ci.hw_channel);
+
+ if (bw_cap == 0 ||
+ (bw_cap == 2 && ci.hw_channel <= 14)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 0;
+ else
+ nrate_list2copy = 1;
+ }
+ if (bw_cap == 1 ||
+ (bw_cap == 2 && ci.hw_channel >= 36)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 2;
+ else
+ nrate_list2copy = 3;
+ }
+ range->num_bitrates += 8;
+ for (k = 0; i < range->num_bitrates; k++, i++) {
+
+ range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
+ }
+ }
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+ return error;
+ i = dtoh32(i);
+ if (i == WLC_PHY_TYPE_A)
+ range->throughput = 24000000;
+ else
+ range->throughput = 1500000;
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
+ range->num_encoding_sizes = 4;
+ range->encoding_size[0] = WEP1_KEY_SIZE;
+ range->encoding_size[1] = WEP128_KEY_SIZE;
+#if WIRELESS_EXT > 17
+ range->encoding_size[2] = TKIP_KEY_SIZE;
+#else
+ range->encoding_size[2] = 0;
+#endif
+ range->encoding_size[3] = AES_KEY_SIZE;
+
+ range->min_pmp = 0;
+ range->max_pmp = 0;
+ range->min_pmt = 0;
+ range->max_pmt = 0;
+ range->pmp_flags = 0;
+ range->pm_capa = 0;
+
+ range->num_txpower = 2;
+ range->txpower[0] = 1;
+ range->txpower[1] = 255;
+ range->txpower_capa = IW_TXPOW_MWATT;
+
+#if WIRELESS_EXT > 10
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 19;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->r_time_flags = 0;
+
+ range->min_retry = 1;
+ range->max_retry = 255;
+
+ range->min_r_time = 0;
+ range->max_r_time = 0;
+#endif
+
+#if WIRELESS_EXT > 17
+ range->enc_capa = IW_ENC_CAPA_WPA;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
+ range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
+ range->enc_capa |= IW_ENC_CAPA_WPA2;
+
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
+
+#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
+
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+#endif
+#endif
+
+ return 0;
+}
+
+static int
+rssi_to_qual(int rssi)
+{
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ return 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ return 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ return 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ return 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ return 4;
+ else
+ return 5;
+}
+
+static int
+wl_iw_set_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ int i;
+
+ WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
+ for (i = 0; i < iw->spy_num; i++)
+ memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
+ memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
+
+ return 0;
+}
+
+static int
+wl_iw_get_spy(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
+ int i;
+
+ WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ dwrq->length = iw->spy_num;
+ for (i = 0; i < iw->spy_num; i++) {
+ memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
+ addr[i].sa_family = AF_UNIX;
+ memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
+ iw->spy_qual[i].updated = 0;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_set_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ int error = -EINVAL;
+#ifdef BCMDBG
+
+#endif
+
+ WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
+
+ if (awrq->sa_family != ARPHRD_ETHER) {
+ WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
+ WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
+ }
+ return 0;
+ }
+
+ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
+ WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_wap(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
+
+ awrq->sa_family = ARPHRD_ETHER;
+ memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
+
+ (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_mlme(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra
+)
+{
+ struct iw_mlme *mlme;
+ scb_val_t scbval;
+ int error = -EINVAL;
+
+ WL_TRACE(("%s: SIOCSIWMLME\n", dev->name));
+
+ mlme = (struct iw_mlme *)extra;
+ if (mlme == NULL) {
+ WL_ERROR(("Invalid ioctl data.\n"));
+ return error;
+ }
+
+ scbval.val = mlme->reason_code;
+ bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
+
+ if (mlme->cmd == IW_MLME_DISASSOC) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+ }
+ else if (mlme->cmd == IW_MLME_DEAUTH) {
+ scbval.val = htod32(scbval.val);
+ error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
+ sizeof(scb_val_t));
+ }
+ else {
+ WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__));
+ return error;
+ }
+
+ return error;
+}
+#endif
+
+static int
+wl_iw_get_aplist(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality qual[IW_MAX_AP];
+ wl_bss_info_t *bi = NULL;
+ int error, i;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+ continue;
+
+ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ addr[dwrq->length].sa_family = ARPHRD_ETHER;
+ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
+ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+ qual[dwrq->length].noise = 0x100 + bi->phy_noise;
+
+#if WIRELESS_EXT > 18
+ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ qual[dwrq->length].updated = 7;
+#endif
+
+ dwrq->length++;
+ }
+
+ kfree(list);
+
+ if (dwrq->length) {
+ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
+
+ dwrq->flags = 1;
+ }
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 13
+static int
+wl_iw_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+
+ WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+
+ memset(&ssid, 0, sizeof(ssid));
+
+#if WIRELESS_EXT > 17
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
+ memcpy(ssid.SSID, req->essid, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+ }
+ }
+#endif
+
+ (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static bool
+ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
+{
+
+ uint8 *ie = *wpaie;
+
+ if ((ie[1] >= 6) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
+ return TRUE;
+ }
+
+ ie += ie[1] + 2;
+
+ *tlvs_len -= (int)(ie - *tlvs);
+
+ *tlvs = ie;
+ return FALSE;
+}
+
+static bool
+ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
+{
+
+ uint8 *ie = *wpsie;
+
+ if ((ie[1] >= 4) &&
+ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
+ return TRUE;
+ }
+
+ ie += ie[1] + 2;
+
+ *tlvs_len -= (int)(ie - *tlvs);
+
+ *tlvs = ie;
+ return FALSE;
+}
+#endif
+
+static int
+wl_iw_handle_scanresults_ies(char **event_p, char *end,
+ struct iw_request_info *info, wl_bss_info_t *bi)
+{
+#if WIRELESS_EXT > 17
+ struct iw_event iwe;
+ char *event;
+
+ event = *event_p;
+ if (bi->ie_length) {
+
+ bcm_tlv_t *ie;
+ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ int ptr_len = bi->ie_length;
+
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+
+ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ *event_p = event;
+ }
+
+#endif
+ return 0;
+}
+static int
+wl_iw_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ channel_info_t ci;
+ wl_scan_results_t *list;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ int error, i, j;
+ char *event = extra, *end = extra + dwrq->length, *value;
+ uint buflen = dwrq->length;
+
+ WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+ return error;
+ ci.scan_channel = dtoh32(ci.scan_channel);
+ if (ci.scan_channel)
+ return -EAGAIN;
+
+ list = kmalloc(buflen, GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
+ kfree(list);
+ return error;
+ }
+ list->buflen = dtoh32(list->buflen);
+ list->version = dtoh32(list->version);
+ list->count = dtoh32(list->count);
+
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ buflen));
+
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
+
+ iwe.u.data.length = dtoh32(bi->SSID_len);
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
+
+ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+ iwe.u.mode = IW_MODE_INFRA;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
+ }
+
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
+ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ iwe.u.freq.e = 6;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
+
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
+ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+ iwe.u.qual.noise = 0x100 + bi->phy_noise;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
+
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
+
+ iwe.cmd = SIOCGIWENCODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
+
+ if (bi->rateset.count) {
+ value = event + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
+ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
+ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ event = value;
+ }
+ }
+
+ kfree(list);
+
+ dwrq->length = event - extra;
+ dwrq->flags = 0;
+
+ return 0;
+}
+
+#endif
+
+static int
+wl_iw_set_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
+
+ memset(&ssid, 0, sizeof(ssid));
+ if (dwrq->length && extra) {
+#if WIRELESS_EXT > 20
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
+#else
+ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
+#endif
+ memcpy(ssid.SSID, extra, ssid.SSID_len);
+ ssid.SSID_len = htod32(ssid.SSID_len);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
+ return error;
+ }
+
+ else {
+ scb_val_t scbval;
+ bzero(&scbval, sizeof(scb_val_t));
+ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
+ return error;
+ }
+ return 0;
+}
+
+static int
+wl_iw_get_essid(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ int error;
+
+ WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
+ WL_ERROR(("Error getting the SSID\n"));
+ return error;
+ }
+
+ ssid.SSID_len = dtoh32(ssid.SSID_len);
+
+ memcpy(extra, ssid.SSID, ssid.SSID_len);
+
+ dwrq->length = ssid.SSID_len;
+
+ dwrq->flags = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if (dwrq->length > sizeof(iw->nickname))
+ return -E2BIG;
+
+ memcpy(iw->nickname, extra, dwrq->length);
+ iw->nickname[dwrq->length - 1] = '\0';
+
+ return 0;
+}
+
+static int
+wl_iw_get_nick(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_iw_t *iw = IW_DEV_IF(dev);
+ WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ strcpy(extra, iw->nickname);
+ dwrq->length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int wl_iw_set_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ wl_rateset_t rateset;
+ int error, rate, i, error_bg, error_a;
+
+ WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ return error;
+
+ rateset.count = dtoh32(rateset.count);
+
+ if (vwrq->value < 0) {
+
+ rate = rateset.rates[rateset.count - 1] & 0x7f;
+ } else if (vwrq->value < rateset.count) {
+
+ rate = rateset.rates[vwrq->value] & 0x7f;
+ } else {
+
+ rate = vwrq->value / 500000;
+ }
+
+ if (vwrq->fixed) {
+
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
+ error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+ } else {
+
+ error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
+
+ error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
+
+ if (error_bg && error_a)
+ return (error_bg | error_a);
+
+ for (i = 0; i < rateset.count; i++)
+ if ((rateset.rates[i] & 0x7f) > rate)
+ break;
+ rateset.count = htod32(i);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
+ return error;
+ }
+
+ return 0;
+}
+
+static int wl_iw_get_rate(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rate;
+
+ WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
+ return error;
+ rate = dtoh32(rate);
+ vwrq->value = rate * 500000;
+
+ return 0;
+}
+
+static int
+wl_iw_set_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
+
+ if (vwrq->disabled)
+ rts = DOT11_DEFAULT_RTS_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
+ return -EINVAL;
+ else
+ rts = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_rts(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, rts;
+
+ WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
+ return error;
+
+ vwrq->value = rts;
+ vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, frag;
+
+ WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
+
+ if (vwrq->disabled)
+ frag = DOT11_DEFAULT_FRAG_LEN;
+ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
+ return -EINVAL;
+ else
+ frag = vwrq->value;
+
+ if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_frag(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, fragthreshold;
+
+ WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
+
+ if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
+ return error;
+
+ vwrq->value = fragthreshold;
+ vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int
+wl_iw_set_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable;
+ uint16 txpwrmw;
+ WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
+
+ disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
+ disable += WL_RADIO_SW_DISABLE << 16;
+
+ disable = htod32(disable);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
+ return error;
+
+ if (disable & WL_RADIO_SW_DISABLE)
+ return 0;
+
+ if (!(vwrq->flags & IW_TXPOW_MWATT))
+ return -EINVAL;
+
+ if (vwrq->value < 0)
+ return 0;
+
+ if (vwrq->value > 0xffff) txpwrmw = 0xffff;
+ else txpwrmw = (uint16)vwrq->value;
+
+ error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
+ return error;
+}
+
+static int
+wl_iw_get_txpow(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, disable, txpwrdbm;
+ uint8 result;
+
+ WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
+ (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
+ return error;
+
+ disable = dtoh32(disable);
+ result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
+ vwrq->value = (int32)bcm_qdbm_to_mw(result);
+ vwrq->fixed = 0;
+ vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
+ vwrq->flags = IW_TXPOW_MWATT;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 10
+static int
+wl_iw_set_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
+
+ if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
+ return -EINVAL;
+
+ if (vwrq->flags & IW_RETRY_LIMIT) {
+
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
+ !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
+#endif
+
+ lrl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
+ return error;
+ }
+
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
+ !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
+#endif
+
+ srl = htod32(vwrq->value);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_get_retry(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, lrl, srl;
+
+ WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
+
+ vwrq->disabled = 0;
+
+ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
+ return error;
+
+ lrl = dtoh32(lrl);
+ srl = dtoh32(srl);
+
+ if (vwrq->flags & IW_RETRY_MAX) {
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ vwrq->value = lrl;
+ } else {
+ vwrq->flags = IW_RETRY_LIMIT;
+ vwrq->value = srl;
+ if (srl != lrl)
+ vwrq->flags |= IW_RETRY_MIN;
+ }
+
+ return 0;
+}
+#endif
+
+static int
+wl_iw_set_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec;
+
+ WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+
+ if (key.index == DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+ } else {
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ return -EINVAL;
+ }
+
+ wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
+ return error;
+
+ if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
+
+ val = htod32(key.index);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ } else {
+ key.len = dwrq->length;
+
+ if (dwrq->length > sizeof(key.data))
+ return -EINVAL;
+
+ memcpy(key.data, extra, dwrq->length);
+
+ key.flags = WL_PRIMARY_KEY;
+ switch (key.len) {
+ case WEP1_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP1;
+ break;
+ case WEP128_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+ case TKIP_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+#endif
+ case AES_KEY_SIZE:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ swap_key_from_BE(&key);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
+ return error;
+ }
+
+ val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
+ val = htod32(val);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_encode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error, val, wsec, auth;
+
+ WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
+
+ bzero(&key, sizeof(wl_wsec_key_t));
+
+ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
+
+ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
+ val = key.index;
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
+ return error;
+ val = dtoh32(val);
+ if (val)
+ break;
+ }
+ } else
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (key.index >= DOT11_MAX_DEFAULT_KEYS)
+ key.index = 0;
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
+ (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
+ return error;
+
+ swap_key_to_BE(&key);
+
+ wsec = dtoh32(wsec);
+ auth = dtoh32(auth);
+
+ dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
+
+ dwrq->flags = key.index + 1;
+ if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
+
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ }
+ if (auth) {
+
+ dwrq->flags |= IW_ENCODE_RESTRICTED;
+ }
+
+ if (dwrq->length && extra)
+ memcpy(extra, key.data, dwrq->length);
+
+ return 0;
+}
+
+static int
+wl_iw_set_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
+
+ pm = vwrq->disabled ? PM_OFF : PM_MAX;
+
+ pm = htod32(pm);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
+ return error;
+
+ return 0;
+}
+
+static int
+wl_iw_get_power(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error, pm;
+
+ WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
+
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
+ return error;
+
+ pm = dtoh32(pm);
+ vwrq->disabled = pm ? 0 : 1;
+ vwrq->flags = IW_POWER_ALL_R;
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+static int
+wl_iw_set_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
+
+ return 0;
+}
+
+static int
+wl_iw_get_wpaie(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *iwp,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
+ iwp->length = 64;
+ dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
+ return 0;
+}
+
+static int
+wl_iw_set_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_wsec_key_t key;
+ int error;
+ struct iw_encode_ext *iwe;
+
+ WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
+
+ memset(&key, 0, sizeof(key));
+ iwe = (struct iw_encode_ext *)extra;
+
+ if (dwrq->flags & IW_ENCODE_DISABLED) {
+
+ }
+
+ key.index = 0;
+ if (dwrq->flags & IW_ENCODE_INDEX)
+ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ key.len = iwe->key_len;
+
+ if (!ETHER_ISMULTI(iwe->addr.sa_data))
+ bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
+
+ if (key.len == 0) {
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("Changing the the primary Key to %d\n", key.index));
+
+ key.index = htod32(key.index);
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
+ &key.index, sizeof(key.index));
+ if (error)
+ return error;
+ }
+
+ else {
+ swap_key_from_BE(&key);
+ dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ }
+ }
+
+ else {
+ if (iwe->key_len > sizeof(key.data))
+ return -EINVAL;
+
+ WL_WSEC(("Setting the key index %d\n", key.index));
+ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ WL_WSEC(("key is a Primary Key\n"));
+ key.flags = WL_PRIMARY_KEY;
+ }
+
+ bcopy((void *)iwe->key, key.data, iwe->key_len);
+
+ if (iwe->alg == IW_ENCODE_ALG_TKIP) {
+ uint8 keybuf[8];
+ bcopy(&key.data[24], keybuf, sizeof(keybuf));
+ bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
+ bcopy(keybuf, &key.data[16], sizeof(keybuf));
+ }
+
+ if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+ uchar *ivptr;
+ ivptr = (uchar *)iwe->rx_seq;
+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+ (ivptr[3] << 8) | ivptr[2];
+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+ key.iv_initialized = TRUE;
+ }
+
+ switch (iwe->alg) {
+ case IW_ENCODE_ALG_NONE:
+ key.algo = CRYPTO_ALGO_OFF;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (iwe->key_len == WEP1_KEY_SIZE)
+ key.algo = CRYPTO_ALGO_WEP1;
+ else
+ key.algo = CRYPTO_ALGO_WEP128;
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ key.algo = CRYPTO_ALGO_TKIP;
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ key.algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ default:
+ break;
+ }
+ swap_key_from_BE(&key);
+
+ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+#if WIRELESS_EXT > 17
+struct {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID-1];
+} pmkid_list;
+static int
+wl_iw_set_pmksa(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ struct iw_pmksa *iwpmksa;
+ uint i;
+ char eabuf[ETHER_ADDR_STR_LEN];
+ pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
+
+ WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
+ iwpmksa = (struct iw_pmksa *)extra;
+ bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
+ if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
+ WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
+ bzero((char *)&pmkid_list, sizeof(pmkid_list));
+ }
+ if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
+ pmkid_list_t pmkid, *pmkidptr;
+ pmkidptr = &pmkid;
+ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
+ {
+ uint j;
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+ for (; i < pmkid_list.pmkids.npmkid; i++) {
+ bcopy(&pmkid_array[i+1].BSSID,
+ &pmkid_array[i].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&pmkid_array[i+1].PMKID,
+ &pmkid_array[i].PMKID,
+ WPA2_PMKID_LEN);
+ }
+ pmkid_list.pmkids.npmkid--;
+ }
+ if (iwpmksa->cmd == IW_PMKSA_ADD) {
+ bcopy(&iwpmksa->bssid.sa_data[0],
+ &pmkid_array[pmkid_list.pmkids.npmkid].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID,
+ WPA2_PMKID_LEN);
+ {
+ uint j;
+ uint k;
+ k = pmkid_list.pmkids.npmkid;
+ BCM_REFERENCE(k);
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkid_array[k].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[k].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ pmkid_list.pmkids.npmkid++;
+ }
+ WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
+ uint j;
+ WL_TRACE(("PMKID[%d]: %s = ", i,
+ bcm_ether_ntoa(&pmkid_array[i].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_array[i].PMKID[j]));
+ printf("\n");
+ }
+ WL_TRACE(("\n"));
+ dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
+ return 0;
+}
+#endif
+
+static int
+wl_iw_get_encodeext(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
+ return 0;
+}
+
+static int
+wl_iw_set_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error = 0;
+ int paramid;
+ int paramval;
+ uint32 cipher_combined;
+ int val = 0;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+ paramval = vwrq->value;
+
+ WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
+ dev->name, paramid, paramval));
+
+ switch (paramid) {
+
+ case IW_AUTH_WPA_VERSION:
+
+ if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
+ val = WPA_AUTH_DISABLED;
+ else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+
+ if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
+ iw->pwsec = paramval;
+ }
+ else {
+ iw->gwsec = paramval;
+ }
+
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+ return error;
+
+ cipher_combined = iw->gwsec | iw->pwsec;
+ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
+ if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+ val |= WEP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_TKIP)
+ val |= TKIP_ENABLED;
+ if (cipher_combined & IW_AUTH_CIPHER_CCMP)
+ val |= AES_ENABLED;
+
+ if (iw->privacy_invoked && !val) {
+ WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
+ "we're a WPS enrollee\n", dev->name, __FUNCTION__));
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else if (val) {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
+ return error;
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA_AUTH_PSK;
+ else
+ val = WPA_AUTH_UNSPECIFIED;
+ }
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA2_AUTH_PSK;
+ else
+ val = WPA2_AUTH_UNSPECIFIED;
+ }
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+
+ WL_ERROR(("Setting the D11auth %d\n", paramval));
+ if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
+ val = 0;
+ else if (paramval & IW_AUTH_ALG_SHARED_KEY)
+ val = 1;
+ else
+ error = 1;
+ if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
+ return error;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (paramval == 0) {
+ val = 0;
+ WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ error = dev_wlc_intvar_set(dev, "wpa_auth", val);
+ return error;
+ }
+ else {
+
+ }
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED: {
+ int wsec;
+
+ if (paramval == 0) {
+ iw->privacy_invoked = FALSE;
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ iw->privacy_invoked = TRUE;
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
+ return error;
+
+ if (!WSEC_ENABLED(wsec)) {
+
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
+ WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ } else {
+ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
+ WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
+ return error;
+ }
+ }
+ }
+ break;
+ }
+
+#endif
+
+ default:
+ break;
+ }
+ return 0;
+}
+#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
+
+static int
+wl_iw_get_wpaauth(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ int error;
+ int paramid;
+ int paramval = 0;
+ int val;
+ wl_iw_t *iw = IW_DEV_IF(dev);
+
+ WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
+
+ paramid = vwrq->flags & IW_AUTH_INDEX;
+
+ switch (paramid) {
+ case IW_AUTH_WPA_VERSION:
+
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
+ paramval = IW_AUTH_WPA_VERSION_DISABLED;
+ else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA;
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
+ paramval = IW_AUTH_WPA_VERSION_WPA2;
+ break;
+
+ case IW_AUTH_CIPHER_PAIRWISE:
+ paramval = iw->pwsec;
+ break;
+
+ case IW_AUTH_CIPHER_GROUP:
+ paramval = iw->gwsec;
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (VAL_PSK(val))
+ paramval = IW_AUTH_KEY_MGMT_PSK;
+ else
+ paramval = IW_AUTH_KEY_MGMT_802_1X;
+
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+
+ if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
+ return error;
+ if (!val)
+ paramval = IW_AUTH_ALG_OPEN_SYSTEM;
+ else
+ paramval = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+ if (val)
+ paramval = TRUE;
+ else
+ paramval = FALSE;
+ break;
+
+#if WIRELESS_EXT > 17
+
+ case IW_AUTH_ROAMING_CONTROL:
+ WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+
+ break;
+
+ case IW_AUTH_PRIVACY_INVOKED:
+ paramval = iw->privacy_invoked;
+ break;
+
+#endif
+ }
+ vwrq->value = paramval;
+ return 0;
+}
+#endif
+
+static const iw_handler wl_iw_handler[] =
+{
+ (iw_handler) wl_iw_config_commit,
+ (iw_handler) wl_iw_get_name,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_freq,
+ (iw_handler) wl_iw_get_freq,
+ (iw_handler) wl_iw_set_mode,
+ (iw_handler) wl_iw_get_mode,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_get_range,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_spy,
+ (iw_handler) wl_iw_get_spy,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_wap,
+ (iw_handler) wl_iw_get_wap,
+#if WIRELESS_EXT > 17
+ (iw_handler) wl_iw_mlme,
+#else
+ (iw_handler) NULL,
+#endif
+ (iw_handler) wl_iw_get_aplist,
+#if WIRELESS_EXT > 13
+ (iw_handler) wl_iw_set_scan,
+ (iw_handler) wl_iw_get_scan,
+#else
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+#endif
+ (iw_handler) wl_iw_set_essid,
+ (iw_handler) wl_iw_get_essid,
+ (iw_handler) wl_iw_set_nick,
+ (iw_handler) wl_iw_get_nick,
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_rate,
+ (iw_handler) wl_iw_get_rate,
+ (iw_handler) wl_iw_set_rts,
+ (iw_handler) wl_iw_get_rts,
+ (iw_handler) wl_iw_set_frag,
+ (iw_handler) wl_iw_get_frag,
+ (iw_handler) wl_iw_set_txpow,
+ (iw_handler) wl_iw_get_txpow,
+#if WIRELESS_EXT > 10
+ (iw_handler) wl_iw_set_retry,
+ (iw_handler) wl_iw_get_retry,
+#endif
+ (iw_handler) wl_iw_set_encode,
+ (iw_handler) wl_iw_get_encode,
+ (iw_handler) wl_iw_set_power,
+ (iw_handler) wl_iw_get_power,
+#if WIRELESS_EXT > 17
+ (iw_handler) NULL,
+ (iw_handler) NULL,
+ (iw_handler) wl_iw_set_wpaie,
+ (iw_handler) wl_iw_get_wpaie,
+ (iw_handler) wl_iw_set_wpaauth,
+ (iw_handler) wl_iw_get_wpaauth,
+ (iw_handler) wl_iw_set_encodeext,
+ (iw_handler) wl_iw_get_encodeext,
+ (iw_handler) wl_iw_set_pmksa,
+#endif
+};
+
+#if WIRELESS_EXT > 12
+enum {
+ WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
+ WL_IW_SET_VLANMODE,
+ WL_IW_SET_PM
+};
+
+static iw_handler wl_iw_priv_handler[] = {
+ wl_iw_set_leddc,
+ wl_iw_set_vlanmode,
+ wl_iw_set_pm
+};
+
+static struct iw_priv_args wl_iw_priv_args[] = {
+ {
+ WL_IW_SET_LEDDC,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_leddc"
+ },
+ {
+ WL_IW_SET_VLANMODE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_vlanmode"
+ },
+ {
+ WL_IW_SET_PM,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 0,
+ "set_pm"
+ }
+};
+
+const struct iw_handler_def wl_iw_handler_def =
+{
+ .num_standard = ARRAYSIZE(wl_iw_handler),
+ .num_private = ARRAY_SIZE(wl_iw_priv_handler),
+ .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
+ .standard = (iw_handler *) wl_iw_handler,
+ .private = wl_iw_priv_handler,
+ .private_args = wl_iw_priv_args,
+#if WIRELESS_EXT >= 19
+ get_wireless_stats: wl_get_wireless_stats,
+#endif
+ };
+#endif
+
+int
+wl_iw_ioctl(
+ struct net_device *dev,
+ struct ifreq *rq,
+ int cmd
+)
+{
+ struct iwreq *wrq = (struct iwreq *) rq;
+ struct iw_request_info info;
+ iw_handler handler;
+ char *extra = NULL;
+ size_t token_size = 1;
+ int max_tokens = 0, ret = 0;
+
+ if (cmd < SIOCIWFIRST ||
+ IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
+ !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)]))
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+
+ case SIOCSIWESSID:
+ case SIOCGIWESSID:
+ case SIOCSIWNICKN:
+ case SIOCGIWNICKN:
+ max_tokens = IW_ESSID_MAX_SIZE + 1;
+ break;
+
+ case SIOCSIWENCODE:
+ case SIOCGIWENCODE:
+#if WIRELESS_EXT > 17
+ case SIOCSIWENCODEEXT:
+ case SIOCGIWENCODEEXT:
+#endif
+ max_tokens = IW_ENCODING_TOKEN_MAX;
+ break;
+
+ case SIOCGIWRANGE:
+ max_tokens = sizeof(struct iw_range);
+ break;
+
+ case SIOCGIWAPLIST:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_AP;
+ break;
+
+#if WIRELESS_EXT > 13
+ case SIOCGIWSCAN:
+ max_tokens = IW_SCAN_MAX_DATA;
+ break;
+#endif
+
+ case SIOCSIWSPY:
+ token_size = sizeof(struct sockaddr);
+ max_tokens = IW_MAX_SPY;
+ break;
+
+ case SIOCGIWSPY:
+ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
+ max_tokens = IW_MAX_SPY;
+ break;
+ default:
+ break;
+ }
+
+ if (max_tokens && wrq->u.data.pointer) {
+ if (wrq->u.data.length > max_tokens)
+ return -E2BIG;
+
+ if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+ }
+
+ info.cmd = cmd;
+ info.flags = 0;
+
+ ret = handler(dev, &info, &wrq->u, extra);
+
+ if (extra) {
+ if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ kfree(extra);
+ }
+
+ return ret;
+}
+
+bool
+wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
+ char* stringBuf, uint buflen)
+{
+ typedef struct conn_fail_event_map_t {
+ uint32 inEvent;
+ uint32 inStatus;
+ uint32 inReason;
+ const char* outName;
+ const char* outCause;
+ } conn_fail_event_map_t;
+
+# define WL_IW_DONT_CARE 9999
+ const conn_fail_event_map_t event_map [] = {
+
+ {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
+ "Conn", "Success"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
+ "Conn", "NoNetworks"},
+ {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ConfigMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
+ "Conn", "EncrypMismatch"},
+ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
+ "Conn", "RsnMismatch"},
+ {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "AuthTimeout"},
+ {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "AuthFail"},
+ {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
+ "Conn", "AuthNoAck"},
+ {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
+ "Conn", "ReassocFail"},
+ {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
+ "Conn", "ReassocTimeout"},
+ {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
+ "Conn", "ReassocAbort"},
+ {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Deauth"},
+ {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "DisassocInd"},
+ {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
+ "Conn", "Disassoc"}
+ };
+
+ const char* name = "";
+ const char* cause = NULL;
+ int i;
+
+ for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) {
+ const conn_fail_event_map_t* row = &event_map[i];
+ if (row->inEvent == event_type &&
+ (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
+ (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
+ name = row->outName;
+ cause = row->outCause;
+ break;
+ }
+ }
+
+ if (cause) {
+ memset(stringBuf, 0, buflen);
+ snprintf(stringBuf, buflen, "%s %s %02d %02d",
+ name, cause, status, reason);
+ WL_TRACE(("Connection status: %s\n", stringBuf));
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+#if (WIRELESS_EXT > 14)
+
+static bool
+wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
+{
+ uint32 event = e->event_type;
+ uint32 status = e->status;
+ uint32 reason = e->reason;
+
+ if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
+ return TRUE;
+ } else
+ {
+ return FALSE;
+ }
+}
+#endif
+
+#ifndef IW_CUSTOM_MAX
+#define IW_CUSTOM_MAX 256
+#endif
+
+void
+wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
+{
+#if WIRELESS_EXT > 13
+ union iwreq_data wrqu;
+ char extra[IW_CUSTOM_MAX + 1];
+ int cmd = 0;
+ uint32 event_type = e->event_type;
+ uint16 flags = e->flags;
+ uint32 datalen = e->datalen;
+ uint32 status = e->status;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ memset(extra, 0, sizeof(extra));
+
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ switch (event_type) {
+ case WLC_E_TXFAIL:
+ cmd = IWEVTXDROP;
+ break;
+#if WIRELESS_EXT > 14
+ case WLC_E_JOIN:
+ case WLC_E_ASSOC_IND:
+ case WLC_E_REASSOC_IND:
+ cmd = IWEVREGISTERED;
+ break;
+ case WLC_E_DEAUTH_IND:
+ case WLC_E_DISASSOC_IND:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ break;
+
+ case WLC_E_LINK:
+ case WLC_E_NDIS_LINK:
+ cmd = SIOCGIWAP;
+ wrqu.data.length = strlen(extra);
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ bzero(&extra, ETHER_ADDR_LEN);
+ }
+ break;
+ case WLC_E_ACTION_FRAME:
+ cmd = IWEVCUSTOM;
+ if (datalen + 1 <= sizeof(extra)) {
+ wrqu.data.length = datalen + 1;
+ extra[0] = WLC_E_ACTION_FRAME;
+ memcpy(&extra[1], data, datalen);
+ WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
+ }
+ break;
+
+ case WLC_E_ACTION_FRAME_COMPLETE:
+ cmd = IWEVCUSTOM;
+ if (sizeof(status) + 1 <= sizeof(extra)) {
+ wrqu.data.length = sizeof(status) + 1;
+ extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
+ memcpy(&extra[1], &status, sizeof(status));
+ WL_TRACE(("wl_iw_event status %d \n", status));
+ }
+ break;
+#endif
+#if WIRELESS_EXT > 17
+ case WLC_E_MIC_ERROR: {
+ struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra;
+ cmd = IWEVMICHAELMICFAILURE;
+ wrqu.data.length = sizeof(struct iw_michaelmicfailure);
+ if (flags & WLC_EVENT_MSG_GROUP)
+ micerrevt->flags |= IW_MICFAILURE_GROUP;
+ else
+ micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
+ memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ micerrevt->src_addr.sa_family = ARPHRD_ETHER;
+
+ break;
+ }
+
+ case WLC_E_ASSOC_REQ_IE:
+ cmd = IWEVASSOCREQIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_ASSOC_RESP_IE:
+ cmd = IWEVASSOCRESPIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_PMKID_CACHE: {
+ struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
+ pmkid_cand_list_t *pmkcandlist;
+ pmkid_cand_t *pmkidcand;
+ int count;
+
+ if (data == NULL)
+ break;
+
+ cmd = IWEVPMKIDCAND;
+ pmkcandlist = data;
+ count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
+ wrqu.data.length = sizeof(struct iw_pmkid_cand);
+ pmkidcand = pmkcandlist->pmkid_cand;
+ while (count) {
+ bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
+ if (pmkidcand->preauth)
+ iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
+ bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
+ ETHER_ADDR_LEN);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ pmkidcand++;
+ count--;
+ }
+ break;
+ }
+#endif
+
+ case WLC_E_SCAN_COMPLETE:
+#if WIRELESS_EXT > 14
+ cmd = SIOCGIWSCAN;
+#endif
+ break;
+
+ default:
+
+ break;
+ }
+
+ if (cmd) {
+ if (cmd == SIOCGIWSCAN)
+ wireless_send_event(dev, cmd, &wrqu, NULL);
+ else
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+
+#if WIRELESS_EXT > 14
+
+ memset(extra, 0, sizeof(extra));
+ if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
+ cmd = IWEVCUSTOM;
+ wrqu.data.length = strlen(extra);
+ wireless_send_event(dev, cmd, &wrqu, extra);
+ }
+#endif
+
+#endif
+}
+
+int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
+{
+ int res = 0;
+ wl_cnt_t cnt;
+ int phy_noise;
+ int rssi;
+ scb_val_t scb_val;
+
+ phy_noise = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
+ goto done;
+
+ phy_noise = dtoh32(phy_noise);
+ WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
+
+ scb_val.val = 0;
+ if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
+ goto done;
+
+ rssi = dtoh32(scb_val.val);
+ WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
+ if (rssi <= WL_IW_RSSI_NO_SIGNAL)
+ wstats->qual.qual = 0;
+ else if (rssi <= WL_IW_RSSI_VERY_LOW)
+ wstats->qual.qual = 1;
+ else if (rssi <= WL_IW_RSSI_LOW)
+ wstats->qual.qual = 2;
+ else if (rssi <= WL_IW_RSSI_GOOD)
+ wstats->qual.qual = 3;
+ else if (rssi <= WL_IW_RSSI_VERY_GOOD)
+ wstats->qual.qual = 4;
+ else
+ wstats->qual.qual = 5;
+
+ wstats->qual.level = 0x100 + rssi;
+ wstats->qual.noise = 0x100 + phy_noise;
+#if WIRELESS_EXT > 18
+ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+ wstats->qual.updated |= 7;
+#endif
+
+#if WIRELESS_EXT > 11
+ WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t)));
+
+ memset(&cnt, 0, sizeof(wl_cnt_t));
+ res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
+ if (res)
+ {
+ WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
+ goto done;
+ }
+
+ cnt.version = dtoh16(cnt.version);
+ if (cnt.version != WL_CNT_T_VERSION) {
+ WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
+ WL_CNT_T_VERSION, cnt.version));
+ goto done;
+ }
+
+ wstats->discard.nwid = 0;
+ wstats->discard.code = dtoh32(cnt.rxundec);
+ wstats->discard.fragment = dtoh32(cnt.rxfragerr);
+ wstats->discard.retries = dtoh32(cnt.txfail);
+ wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
+ wstats->miss.beacon = 0;
+
+ WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
+ dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
+
+#endif
+
+done:
+ return res;
+}
+
+int
+wl_iw_attach(struct net_device *dev, void * dhdp)
+{
+ return 0;
+}
+
+void wl_iw_detach(void)
+{
+}
+
+#endif
diff --git a/src/wl/sys/wl_iw.h b/src/wl/sys/wl_iw.h
new file mode 100644
index 0000000..3ab084f
--- /dev/null
+++ b/src/wl/sys/wl_iw.h
@@ -0,0 +1,150 @@
+/*
+ * Linux Wireless Extensions support
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_iw.h 291086 2011-10-21 01:17:24Z $
+ */
+
+#ifndef _wl_iw_h_
+#define _wl_iw_h_
+
+#include <linux/wireless.h>
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <wlioctl.h>
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define GET_SSID "SSID="
+#define GET_CHANNEL "CH="
+#define GET_NPROBE "NPROBE="
+#define GET_ACTIVE_ASSOC_DWELL "ACTIVE="
+#define GET_PASSIVE_ASSOC_DWELL "PASSIVE="
+#define GET_HOME_DWELL "HOME="
+#define GET_SCAN_TYPE "TYPE="
+
+#define BAND_GET_CMD "GETBAND"
+#define BAND_SET_CMD "SETBAND"
+#define DTIM_SKIP_GET_CMD "DTIMSKIPGET"
+#define DTIM_SKIP_SET_CMD "DTIMSKIPSET"
+#define SETSUSPEND_CMD "SETSUSPENDOPT"
+#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR"
+
+#define PNOSETUP_SET_CMD "PNOSETUP "
+#define PNOENABLE_SET_CMD "PNOFORCE"
+#define PNODEBUG_SET_CMD "PNODEBUG"
+#define TXPOWER_SET_CMD "TXPOWER"
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+typedef struct wl_iw_extra_params {
+ int target_channel;
+} wl_iw_extra_params_t;
+
+struct cntry_locales_custom {
+ char iso_abbrev[WLC_CNTRY_BUF_SZ];
+ char custom_locale[WLC_CNTRY_BUF_SZ];
+ int32 custom_locale_rev;
+};
+
+#define WL_IW_RSSI_MINVAL -200
+#define WL_IW_RSSI_NO_SIGNAL -91
+#define WL_IW_RSSI_VERY_LOW -80
+#define WL_IW_RSSI_LOW -70
+#define WL_IW_RSSI_GOOD -68
+#define WL_IW_RSSI_VERY_GOOD -58
+#define WL_IW_RSSI_EXCELLENT -57
+#define WL_IW_RSSI_INVALID 0
+#define MAX_WX_STRING 80
+#define isprint(c) bcm_isprint(c)
+#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1)
+#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3)
+#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5)
+#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7)
+#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9)
+#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11)
+#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13)
+
+#define G_SCAN_RESULTS 8*1024
+#define WE_ADD_EVENT_FIX 0x80
+#define G_WLAN_SET_ON 0
+#define G_WLAN_SET_OFF 1
+
+typedef struct wl_iw {
+ char nickname[IW_ESSID_MAX_SIZE];
+
+ struct iw_statistics wstats;
+
+ int spy_num;
+ uint32 pwsec;
+ uint32 gwsec;
+ bool privacy_invoked;
+ struct ether_addr spy_addr[IW_MAX_SPY];
+ struct iw_quality spy_qual[IW_MAX_SPY];
+ void *wlinfo;
+} wl_iw_t;
+
+struct wl_ctrl {
+ struct timer_list *timer;
+ struct net_device *dev;
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+};
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+extern const struct iw_handler_def wl_iw_handler_def;
+#endif
+
+extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
+extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
+int wl_iw_attach(struct net_device *dev, void * dhdp);
+int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+
+void wl_iw_detach(void);
+
+#define CSCAN_COMMAND "CSCAN "
+#define CSCAN_TLV_PREFIX 'S'
+#define CSCAN_TLV_VERSION 1
+#define CSCAN_TLV_SUBVERSION 0
+#define CSCAN_TLV_TYPE_SSID_IE 'S'
+#define CSCAN_TLV_TYPE_CHANNEL_IE 'C'
+#define CSCAN_TLV_TYPE_NPROBE_IE 'N'
+#define CSCAN_TLV_TYPE_ACTIVE_IE 'A'
+#define CSCAN_TLV_TYPE_PASSIVE_IE 'P'
+#define CSCAN_TLV_TYPE_HOME_IE 'H'
+#define CSCAN_TLV_TYPE_STYPE_IE 'T'
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(info, stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(info, event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(info, stream, ends, iwe, extra)
+#else
+#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_event(stream, ends, iwe, extra)
+#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
+ iwe_stream_add_value(event, value, ends, iwe, event_len)
+#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
+ iwe_stream_add_point(stream, ends, iwe, extra)
+#endif
+
+#endif
diff --git a/src/wl/sys/wl_linux.c b/src/wl/sys/wl_linux.c
new file mode 100644
index 0000000..0d05100
--- /dev/null
+++ b/src/wl/sys/wl_linux.c
@@ -0,0 +1,3371 @@
+/*
+ * Linux-specific portion of
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_linux.c 580354 2015-08-18 23:42:37Z $
+ */
+
+#define LINUX_PORT
+
+#define __UNDEF_NO_VERSION__
+
+#include <typedefs.h>
+#include <linuxver.h>
+#include <osl.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#include <linux/module.h>
+#endif
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ethtool.h>
+#include <linux/completion.h>
+#include <linux/usb.h>
+#include <linux/pci_ids.h>
+#define WLC_MAXBSSCFG 1
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#include <asm/switch_to.h>
+#else
+#include <asm/system.h>
+#endif
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <proto/802.1d.h>
+
+#include <epivers.h>
+#include <bcmendian.h>
+#include <proto/ethernet.h>
+#include <bcmutils.h>
+#include <pcicfg.h>
+#include <wlioctl.h>
+#include <wlc_key.h>
+#include <siutils.h>
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5)
+#error "No support for Kernel Rev <= 2.4.5, As the older kernel revs doesn't support Tasklets"
+#endif
+
+#include <wlc_pub.h>
+#include <wl_dbg.h>
+#include <wlc_ethereal.h>
+#include <proto/ieee80211_radiotap.h>
+
+#include <wl_iw.h>
+#ifdef USE_IW
+struct iw_statistics *wl_get_wireless_stats(struct net_device *dev);
+#endif
+
+#include <wl_export.h>
+
+#include <wl_linux.h>
+
+#if defined(USE_CFG80211)
+#include <wl_cfg80211_hybrid.h>
+#endif
+
+#include <wlc_wowl.h>
+
+static void wl_timer(ulong data);
+static void _wl_timer(wl_timer_t *t);
+static struct net_device *wl_alloc_linux_if(wl_if_t *wlif);
+
+static int wl_monitor_start(struct sk_buff *skb, struct net_device *dev);
+
+static void wl_start_txqwork(wl_task_t *task);
+static void wl_txq_free(wl_info_t *wl);
+#define TXQ_LOCK(_wl) spin_lock_bh(&(_wl)->txq_lock)
+#define TXQ_UNLOCK(_wl) spin_unlock_bh(&(_wl)->txq_lock)
+
+static void wl_set_multicast_list_workitem(struct work_struct *work);
+
+static void wl_timer_task(wl_task_t *task);
+static void wl_dpc_rxwork(struct wl_task *task);
+
+static int wl_reg_proc_entry(wl_info_t *wl);
+
+static int wl_linux_watchdog(void *ctx);
+static
+int wl_found = 0;
+
+typedef struct priv_link {
+ wl_if_t *wlif;
+} priv_link_t;
+
+#define WL_DEV_IF(dev) ((wl_if_t*)((priv_link_t*)DEV_PRIV(dev))->wlif)
+
+#ifdef WL_INFO
+#undef WL_INFO
+#endif
+#define WL_INFO(dev) ((wl_info_t*)(WL_DEV_IF(dev)->wl))
+
+static int wl_open(struct net_device *dev);
+static int wl_close(struct net_device *dev);
+static int BCMFASTPATH wl_start(struct sk_buff *skb, struct net_device *dev);
+static int wl_start_int(wl_info_t *wl, wl_if_t *wlif, struct sk_buff *skb);
+
+static struct net_device_stats *wl_get_stats(struct net_device *dev);
+static int wl_set_mac_address(struct net_device *dev, void *addr);
+static void wl_set_multicast_list(struct net_device *dev);
+static void _wl_set_multicast_list(struct net_device *dev);
+static int wl_ethtool(wl_info_t *wl, void *uaddr, wl_if_t *wlif);
+static void wl_dpc(ulong data);
+static void wl_tx_tasklet(ulong data);
+static void wl_link_up(wl_info_t *wl, char * ifname);
+static void wl_link_down(wl_info_t *wl, char *ifname);
+static int wl_schedule_task(wl_info_t *wl, void (*fn)(struct wl_task *), void *context);
+#if defined(BCMDBG)
+static int wl_dump(wl_info_t *wl, struct bcmstrbuf *b);
+#endif
+static struct wl_if *wl_alloc_if(wl_info_t *wl, int iftype, uint unit, struct wlc_if* wlc_if);
+static void wl_free_if(wl_info_t *wl, wl_if_t *wlif);
+static void wl_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info);
+
+#if defined(WL_CONFIG_RFKILL)
+#include <linux/rfkill.h>
+static int wl_init_rfkill(wl_info_t *wl);
+static void wl_uninit_rfkill(wl_info_t *wl);
+static int wl_set_radio_block(void *data, bool blocked);
+static void wl_report_radio_state(wl_info_t *wl);
+#endif
+
+MODULE_LICENSE("MIXED/Proprietary");
+
+static struct pci_device_id wl_id_table[] =
+{
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, wl_id_table);
+
+static unsigned int online_cpus = 1;
+
+#ifdef BCMDBG
+static int msglevel = 0xdeadbeef;
+module_param(msglevel, int, 0);
+static int msglevel2 = 0xdeadbeef;
+module_param(msglevel2, int, 0);
+static int phymsglevel = 0xdeadbeef;
+module_param(phymsglevel, int, 0);
+#endif
+
+#ifdef BCMDBG_ASSERT
+static int assert_type = 0xdeadbeef;
+module_param(assert_type, int, 0);
+#endif
+
+static int passivemode = 0;
+module_param(passivemode, int, 0);
+
+#define WL_TXQ_THRESH 0
+static int wl_txq_thresh = WL_TXQ_THRESH;
+module_param(wl_txq_thresh, int, 0);
+
+static int oneonly = 0;
+module_param(oneonly, int, 0);
+
+static int piomode = 0;
+module_param(piomode, int, 0);
+
+static int instance_base = 0;
+module_param(instance_base, int, 0);
+
+#if defined(BCMDBG)
+static struct ether_addr local_ea;
+static char *macaddr = NULL;
+module_param(macaddr, charp, S_IRUGO);
+#endif
+
+static int nompc = 0;
+module_param(nompc, int, 0);
+
+#ifdef quote_str
+#undef quote_str
+#endif
+#ifdef to_str
+#undef to_str
+#endif
+#define to_str(s) #s
+#define quote_str(s) to_str(s)
+
+#define BRCM_WLAN_IFNAME eth%d
+
+static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME);
+
+module_param_string(intf_name, intf_name, IFNAMSIZ, 0);
+
+static const u_int8_t brcm_oui[] = {0x00, 0x10, 0x18};
+
+#define WL_RADIOTAP_BRCM2_HT_SNS 0x01
+#define WL_RADIOTAP_BRCM2_HT_MCS 0x00000001
+
+#define WL_RADIOTAP_LEGACY_SNS 0x02
+#define WL_RADIOTAP_LEGACY_VHT 0x00000001
+
+#define IEEE80211_RADIOTAP_HTMOD_40 0x01
+#define IEEE80211_RADIOTAP_HTMOD_SGI 0x02
+#define IEEE80211_RADIOTAP_HTMOD_GF 0x04
+#define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08
+#define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30
+#define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4
+
+#define WL_RADIOTAP_F_NONHT_VHT_DYN_BW 0x01
+
+#define WL_RADIOTAP_F_NONHT_VHT_BW 0x02
+
+struct wl_radiotap_nonht_vht {
+ u_int8_t len;
+ u_int8_t flags;
+ u_int8_t bw;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_nonht_vht wl_radiotap_nonht_vht_t;
+
+struct wl_radiotap_legacy {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ uint8 flags;
+ uint8 rate;
+ uint16 channel_freq;
+ uint16 channel_flags;
+ uint8 signal;
+ uint8 noise;
+ int8 antenna;
+ uint8 pad2;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ wl_radiotap_nonht_vht_t nonht_vht;
+} __attribute__ ((__packed__));
+
+typedef struct wl_radiotap_legacy wl_radiotap_legacy_t;
+
+#define WL_RADIOTAP_LEGACY_SKIP_LEN htol16(sizeof(struct wl_radiotap_legacy) - \
+ offsetof(struct wl_radiotap_legacy, nonht_vht))
+
+#define WL_RADIOTAP_NONHT_VHT_LEN (sizeof(wl_radiotap_nonht_vht_t) - 1)
+
+struct wl_radiotap_ht_brcm_2 {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad2;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t pad3;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ u_int8_t mcs;
+ u_int8_t htflags;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht_brcm_2 wl_radiotap_ht_brcm_2_t;
+
+#define WL_RADIOTAP_HT_BRCM2_SKIP_LEN htol16(sizeof(struct wl_radiotap_ht_brcm_2) - \
+ offsetof(struct wl_radiotap_ht_brcm_2, mcs))
+
+struct wl_radiotap_ht_brcm_3 {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ u_int32_t it_present_ext;
+ u_int32_t pad1;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad2;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t mcs_known;
+ u_int8_t mcs_flags;
+ u_int8_t mcs_index;
+ u_int8_t vend_oui[3];
+ u_int8_t vend_sns;
+ u_int16_t vend_skip_len;
+ wl_radiotap_nonht_vht_t nonht_vht;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht_brcm_3 wl_radiotap_ht_brcm_3_t;
+
+struct wl_radiotap_ht {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad1;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t mcs_known;
+ u_int8_t mcs_flags;
+ u_int8_t mcs_index;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_ht wl_radiotap_ht_t;
+
+struct wl_radiotap_vht {
+ struct ieee80211_radiotap_header ieee_radiotap;
+ uint32 tsft_l;
+ uint32 tsft_h;
+ u_int8_t flags;
+ u_int8_t pad1;
+ u_int16_t channel_freq;
+ u_int16_t channel_flags;
+ u_int8_t signal;
+ u_int8_t noise;
+ u_int8_t antenna;
+ u_int8_t pad2;
+ u_int16_t pad3;
+ uint32 ampdu_ref_num;
+ u_int16_t ampdu_flags;
+ u_int8_t ampdu_delim_crc;
+ u_int8_t ampdu_reserved;
+ u_int16_t vht_known;
+ u_int8_t vht_flags;
+ u_int8_t vht_bw;
+ u_int8_t vht_mcs_nss[4];
+ u_int8_t vht_coding;
+ u_int8_t vht_group_id;
+ u_int16_t vht_partial_aid;
+} __attribute__ ((packed));
+
+typedef struct wl_radiotap_vht wl_radiotap_vht_t;
+
+#define WL_RADIOTAP_PRESENT_LEGACY \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \
+ (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WL_RADIOTAP_PRESENT_HT_BRCM2 \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \
+ (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WL_RADIOTAP_PRESENT_HT \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_MCS))
+
+#define WL_RADIOTAP_PRESENT_VHT \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_AMPDU) | \
+ (1 << IEEE80211_RADIOTAP_VHT))
+
+#ifndef ARPHRD_IEEE80211_RADIOTAP
+#define ARPHRD_IEEE80211_RADIOTAP 803
+#endif
+
+#ifndef SRCBASE
+#define SRCBASE "."
+#endif
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static struct ethtool_ops wl_ethtool_ops =
+#else
+static const struct ethtool_ops wl_ethtool_ops =
+#endif
+{
+ .get_drvinfo = wl_get_driver_info,
+};
+#endif
+
+#if defined(WL_USE_NETDEV_OPS)
+
+static const struct net_device_ops wl_netdev_ops =
+{
+ .ndo_open = wl_open,
+ .ndo_stop = wl_close,
+ .ndo_start_xmit = wl_start,
+ .ndo_get_stats = wl_get_stats,
+ .ndo_set_mac_address = wl_set_mac_address,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
+ .ndo_set_rx_mode = wl_set_multicast_list,
+#else
+ .ndo_set_multicast_list = wl_set_multicast_list,
+#endif
+ .ndo_do_ioctl = wl_ioctl
+};
+
+static const struct net_device_ops wl_netdev_monitor_ops =
+{
+ .ndo_start_xmit = wl_monitor_start,
+ .ndo_get_stats = wl_get_stats,
+ .ndo_do_ioctl = wl_ioctl
+};
+#endif
+
+static void
+wl_if_setup(struct net_device *dev)
+{
+#if defined(WL_USE_NETDEV_OPS)
+ dev->netdev_ops = &wl_netdev_ops;
+#else
+ dev->open = wl_open;
+ dev->stop = wl_close;
+ dev->hard_start_xmit = wl_start;
+ dev->get_stats = wl_get_stats;
+ dev->set_mac_address = wl_set_mac_address;
+ dev->set_multicast_list = wl_set_multicast_list;
+ dev->do_ioctl = wl_ioctl;
+#endif
+
+#ifdef USE_IW
+#if WIRELESS_EXT < 19
+ dev->get_wireless_stats = wl_get_wireless_stats;
+#endif
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = (struct iw_handler_def *) &wl_iw_handler_def;
+#endif
+#endif
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+ dev->ethtool_ops = &wl_ethtool_ops;
+#endif
+}
+
+static wl_info_t *
+wl_attach(uint16 vendor, uint16 device, ulong regs,
+ uint bustype, void *btparam, uint irq, uchar* bar1_addr, uint32 bar1_size)
+{
+ struct net_device *dev;
+ wl_if_t *wlif;
+ wl_info_t *wl;
+ osl_t *osh;
+ int unit, err;
+#if defined(USE_CFG80211)
+ struct device *parentdev;
+#endif
+
+ unit = wl_found + instance_base;
+ err = 0;
+
+ if (unit < 0) {
+ WL_ERROR(("wl%d: unit number overflow, exiting\n", unit));
+ return NULL;
+ }
+
+ if (oneonly && (unit != instance_base)) {
+ WL_ERROR(("wl%d: wl_attach: oneonly is set, exiting\n", unit));
+ return NULL;
+ }
+
+ osh = osl_attach(btparam, bustype, TRUE);
+ ASSERT(osh);
+
+ if ((wl = (wl_info_t*) MALLOC(osh, sizeof(wl_info_t))) == NULL) {
+ WL_ERROR(("wl%d: malloc wl_info_t, out of memory, malloced %d bytes\n", unit,
+ MALLOCED(osh)));
+ osl_detach(osh);
+ return NULL;
+ }
+ bzero(wl, sizeof(wl_info_t));
+
+ wl->osh = osh;
+ wl->unit = unit;
+ atomic_set(&wl->callbacks, 0);
+
+ wl->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE;
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+
+ MY_INIT_WORK(&wl->txq_task.work, (work_func_t)wl_start_txqwork);
+ wl->txq_task.context = wl;
+
+ MY_INIT_WORK(&wl->multicast_task.work, (work_func_t)wl_set_multicast_list_workitem);
+
+ MY_INIT_WORK(&wl->wl_dpc_task.work, (work_func_t)wl_dpc_rxwork);
+ wl->wl_dpc_task.context = wl;
+ }
+
+ wl->txq_dispatched = FALSE;
+ wl->txq_head = wl->txq_tail = NULL;
+ wl->txq_cnt = 0;
+
+ wlif = wl_alloc_if(wl, WL_IFTYPE_BSS, unit, NULL);
+ if (!wlif) {
+ WL_ERROR(("wl%d: %s: wl_alloc_if failed\n", unit, __FUNCTION__));
+ MFREE(osh, wl, sizeof(wl_info_t));
+ osl_detach(osh);
+ return NULL;
+ }
+
+ if (wl_alloc_linux_if(wlif) == NULL) {
+ WL_ERROR(("wl%d: %s: wl_alloc_linux_if failed\n", unit, __FUNCTION__));
+ MFREE(osh, wl, sizeof(wl_info_t));
+ osl_detach(osh);
+ return NULL;
+ }
+
+ dev = wlif->dev;
+ wl->dev = dev;
+ wl_if_setup(dev);
+
+ dev->base_addr = regs;
+
+ WL_TRACE(("wl%d: Bus: ", unit));
+ if (bustype == PCMCIA_BUS) {
+
+ wl->piomode = TRUE;
+ WL_TRACE(("PCMCIA\n"));
+ } else if (bustype == PCI_BUS) {
+
+ wl->piomode = piomode;
+ WL_TRACE(("PCI/%s\n", wl->piomode ? "PIO" : "DMA"));
+ }
+ else if (bustype == RPC_BUS) {
+
+ } else {
+ bustype = PCI_BUS;
+ WL_TRACE(("force to PCI\n"));
+ }
+ wl->bcm_bustype = bustype;
+
+ if ((wl->regsva = ioremap_nocache(dev->base_addr, PCI_BAR0_WINSZ)) == NULL) {
+ WL_ERROR(("wl%d: ioremap() failed\n", unit));
+ goto fail;
+ }
+
+ wl->bar1_addr = bar1_addr;
+ wl->bar1_size = bar1_size;
+
+ spin_lock_init(&wl->lock);
+ spin_lock_init(&wl->isr_lock);
+
+ if (WL_ALL_PASSIVE_ENAB(wl))
+ sema_init(&wl->sem, 1);
+
+ spin_lock_init(&wl->txq_lock);
+
+ if (!(wl->wlc = wlc_attach((void *) wl, vendor, device, unit, wl->piomode,
+ osh, wl->regsva, wl->bcm_bustype, btparam, &err))) {
+ printf("wl driver %s failed with code %d\n", EPI_VERSION_STR, err);
+ goto fail;
+ }
+ wl->pub = wlc_pub(wl->wlc);
+
+ wlif->wlcif = wlc_wlcif_get_by_index(wl->wlc, 0);
+
+ if (nompc) {
+ if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
+ WL_ERROR(("wl%d: Error setting MPC variable to 0\n", unit));
+ }
+ }
+
+ wlc_iovar_setint(wl->wlc, "scan_passive_time", 170);
+
+ wlc_iovar_setint(wl->wlc, "qtxpower", 23 * 4);
+
+#ifdef BCMDBG
+ if (macaddr != NULL) {
+ int dbg_err;
+
+ WL_ERROR(("wl%d: setting MAC ADDRESS %s\n", unit, macaddr));
+ bcm_ether_atoe(macaddr, &local_ea);
+
+ dbg_err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, &local_ea,
+ ETHER_ADDR_LEN, IOV_SET, NULL);
+ if (dbg_err)
+ WL_ERROR(("wl%d: Error setting MAC ADDRESS\n", unit));
+ }
+#endif
+ bcopy(&wl->pub->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN);
+
+ online_cpus = 1;
+
+ WL_ERROR(("wl%d: online cpus %d\n", unit, online_cpus));
+
+ tasklet_init(&wl->tasklet, wl_dpc, (ulong)wl);
+
+ tasklet_init(&wl->tx_tasklet, wl_tx_tasklet, (ulong)wl);
+
+ {
+ if (request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl)) {
+ WL_ERROR(("wl%d: request_irq() failed\n", unit));
+ goto fail;
+ }
+ dev->irq = irq;
+ }
+
+#if defined(USE_IW)
+ WL_ERROR(("Using Wireless Extension\n"));
+#endif
+
+#if defined(USE_CFG80211)
+ parentdev = NULL;
+ if (wl->bcm_bustype == PCI_BUS) {
+ parentdev = &((struct pci_dev *)btparam)->dev;
+ }
+ if (parentdev) {
+ if (wl_cfg80211_attach(dev, parentdev, WL_ALL_PASSIVE_ENAB(wl))) {
+ goto fail;
+ }
+ }
+ else {
+ WL_ERROR(("unsupported bus type\n"));
+ goto fail;
+ }
+#else
+
+ if (wl->bcm_bustype == PCI_BUS) {
+ struct pci_dev *pci_dev = (struct pci_dev *)btparam;
+ if (pci_dev != NULL)
+ SET_NETDEV_DEV(dev, &pci_dev->dev);
+ }
+#endif
+
+ if (register_netdev(dev)) {
+ WL_ERROR(("wl%d: register_netdev() failed\n", unit));
+ goto fail;
+ }
+ wlif->dev_registed = TRUE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#endif
+#ifdef USE_IW
+ wlif->iw.wlinfo = (void *)wl;
+#endif
+
+#if defined(WL_CONFIG_RFKILL)
+ if (wl_init_rfkill(wl) < 0)
+ WL_ERROR(("%s: init_rfkill_failure\n", __FUNCTION__));
+#endif
+
+ if (wlc_iovar_setint(wl->wlc, "leddc", 0xa0000)) {
+ WL_ERROR(("wl%d: Error setting led duty-cycle\n", unit));
+ }
+ if (wlc_set(wl->wlc, WLC_SET_PM, PM_FAST)) {
+ WL_ERROR(("wl%d: Error setting PM variable to FAST PS\n", unit));
+ }
+
+ if (wlc_iovar_setint(wl->wlc, "vlan_mode", OFF)) {
+ WL_ERROR(("wl%d: Error setting vlan mode OFF\n", unit));
+ }
+
+ if (wlc_set(wl->wlc, WLC_SET_INFRA, 1)) {
+ WL_ERROR(("wl%d: Error setting infra_mode to infrastructure\n", unit));
+ }
+
+ if (wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL, NULL)) {
+ WL_ERROR(("wl%d: %s wlc_module_register() failed\n",
+ wl->pub->unit, __FUNCTION__));
+ goto fail;
+ }
+
+#ifdef BCMDBG
+ wlc_dump_register(wl->pub, "wl", (dump_fn_t)wl_dump, (void *)wl);
+#endif
+
+ wl_reg_proc_entry(wl);
+
+ printf("%s: Broadcom BCM%04x 802.11 Hybrid Wireless Controller%s %s",
+ dev->name, device,
+ WL_ALL_PASSIVE_ENAB(wl) ? ", Passive Mode" : "", EPI_VERSION_STR);
+
+#ifdef BCMDBG
+ printf(" (Compiled in " SRCBASE " at " __TIME__ " on " __DATE__ ")");
+#endif
+ printf("\n");
+
+ wl_found++;
+ return wl;
+
+fail:
+ wl_free(wl);
+ return NULL;
+}
+
+static void __devexit wl_remove(struct pci_dev *pdev);
+
+int __devinit
+wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int rc;
+ wl_info_t *wl;
+ uint32 val;
+ uint32 bar1_size = 0;
+ void* bar1_addr = NULL;
+
+ WL_TRACE(("%s: bus %d slot %d func %d irq %d\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq));
+
+ if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
+ (((pdev->device & 0xff00) != 0x4300) &&
+ (pdev->device != 0x576) &&
+ ((pdev->device & 0xff00) != 0x4700) &&
+ ((pdev->device < 43000) || (pdev->device > 43999)))) {
+ WL_TRACE(("%s: unsupported vendor %x device %x\n", __FUNCTION__,
+ pdev->vendor, pdev->device));
+ return (-ENODEV);
+ }
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ WL_ERROR(("%s: Cannot enable device %d-%d_%d\n", __FUNCTION__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
+ return (-ENODEV);
+ }
+ pci_set_master(pdev);
+
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ bar1_size = pci_resource_len(pdev, 2);
+ bar1_addr = (uchar *)ioremap_nocache(pci_resource_start(pdev, 2),
+ bar1_size);
+ wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0), PCI_BUS, pdev,
+ pdev->irq, bar1_addr, bar1_size);
+
+ if (!wl)
+ return -ENODEV;
+
+ pci_set_drvdata(pdev, wl);
+
+ return 0;
+}
+
+static int
+#if !defined(SIMPLE_DEV_PM_OPS)
+wl_suspend(struct pci_dev *pdev, DRV_SUSPEND_STATE_TYPE state)
+{
+#else
+wl_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+#endif
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+ if (!wl) {
+ WL_ERROR(("wl: wl_suspend: pci_get_drvdata failed\n"));
+ return -ENODEV;
+ }
+ WL_ERROR(("%s: PCI Suspend handler\n", __FUNCTION__));
+
+ WL_LOCK(wl);
+ if (WLOFFLD_ENAB(wl->pub) && wlc_iovar_setint(wl->wlc, "wowl_activate", 1) == 0) {
+ WL_TRACE(("%s: Enabled WOWL OFFLOAD\n", __FUNCTION__));
+ } else {
+ WL_ERROR(("%s: Not WOWL capable\n", __FUNCTION__));
+ wl_down(wl);
+ wl->pub->hw_up = FALSE;
+ }
+ WL_UNLOCK(wl);
+
+ if (BUSTYPE(wl->pub->sih->bustype) == PCI_BUS)
+ si_pci_sleep(wl->pub->sih);
+
+ return 0;
+}
+
+static int
+#if !defined(SIMPLE_DEV_PM_OPS)
+wl_resume(struct pci_dev *pdev)
+{
+#else
+wl_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+#endif
+ int err = 0;
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+ if (!wl) {
+ WL_ERROR(("wl: wl_resume: pci_get_drvdata failed\n"));
+ return -ENODEV;
+ }
+
+ WL_ERROR(("%s: PCI Resume handler\n", __FUNCTION__));
+ if (WLOFFLD_ENAB(wl->pub)) {
+ wlc_iovar_setint(wl->wlc, "wowl_activate", 0);
+ wlc_wowl_wake_reason_process(wl->wlc);
+
+ if (WOWL_ACTIVE(wl->pub)) {
+ if (BUSTYPE(wl->pub->sih->bustype) == PCI_BUS) {
+ si_pci_pmeclr(wl->pub->sih);
+ }
+ }
+ }
+
+ WL_LOCK(wl);
+ err = wl_up(wl);
+ WL_UNLOCK(wl);
+
+ return (err);
+}
+
+static void __devexit
+wl_remove(struct pci_dev *pdev)
+{
+ wl_info_t *wl = (wl_info_t *) pci_get_drvdata(pdev);
+
+ if (!wl) {
+ WL_ERROR(("wl: wl_remove: pci_get_drvdata failed\n"));
+ return;
+ }
+ if (!wlc_chipmatch(pdev->vendor, pdev->device)) {
+ WL_ERROR(("wl: wl_remove: wlc_chipmatch failed\n"));
+ return;
+ }
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d (%s): wl_remove() -> wl_down()\n", wl->pub->unit, wl->dev->name));
+ wl_down(wl);
+ WL_UNLOCK(wl);
+
+ wl_free(wl);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+#if defined(SIMPLE_DEV_PM_OPS)
+static SIMPLE_DEV_PM_OPS(wl_pm_ops, wl_suspend, wl_resume);
+#endif
+
+static struct pci_driver wl_pci_driver __refdata = {
+ .name = "wl",
+ .probe = wl_pci_probe,
+ .remove = __devexit_p(wl_remove),
+ .id_table = wl_id_table,
+#ifdef SIMPLE_DEV_PM_OPS
+ .driver.pm = &wl_pm_ops,
+#else
+ .suspend = wl_suspend,
+ .resume = wl_resume,
+#endif
+};
+
+static int __init
+wl_module_init(void)
+{
+ int error = -ENODEV;
+
+#ifdef BCMDBG
+ if (msglevel != 0xdeadbeef)
+ wl_msg_level = msglevel;
+ else {
+ const char *var = getvar(NULL, "wl_msglevel");
+ if (var)
+ wl_msg_level = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: msglevel set to 0x%x\n", __FUNCTION__, wl_msg_level);
+ if (msglevel2 != 0xdeadbeef)
+ wl_msg_level2 = msglevel2;
+ else {
+ const char *var = getvar(NULL, "wl_msglevel2");
+ if (var)
+ wl_msg_level2 = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: msglevel2 set to 0x%x\n", __FUNCTION__, wl_msg_level2);
+ {
+ extern uint32 phyhal_msg_level;
+
+ if (phymsglevel != 0xdeadbeef)
+ phyhal_msg_level = phymsglevel;
+ else {
+ const char *var = getvar(NULL, "phy_msglevel");
+ if (var)
+ phyhal_msg_level = bcm_strtoul(var, NULL, 0);
+ }
+ printf("%s: phymsglevel set to 0x%x\n", __FUNCTION__, phyhal_msg_level);
+ }
+#endif
+
+ {
+ const char *var = getvar(NULL, "wl_dispatch_mode");
+ if (var)
+ passivemode = bcm_strtoul(var, NULL, 0);
+ if (passivemode)
+ printf("%s: passivemode enabled\n", __FUNCTION__);
+ }
+
+#ifdef BCMDBG_ASSERT
+
+ if (assert_type != 0xdeadbeef)
+ g_assert_type = assert_type;
+#endif
+
+ {
+ char *var = getvar(NULL, "wl_txq_thresh");
+ if (var)
+ wl_txq_thresh = bcm_strtoul(var, NULL, 0);
+#ifdef BCMDBG
+ WL_INFORM(("%s: wl_txq_thresh set to 0x%x\n",
+ __FUNCTION__, wl_txq_thresh));
+#endif
+ }
+
+ if (!(error = pci_module_init(&wl_pci_driver)))
+ return (0);
+
+ return (error);
+}
+
+static void __exit
+wl_module_exit(void)
+{
+
+ pci_unregister_driver(&wl_pci_driver);
+
+}
+
+module_init(wl_module_init);
+module_exit(wl_module_exit);
+
+void
+wl_free(wl_info_t *wl)
+{
+ wl_timer_t *t, *next;
+ osl_t *osh;
+
+ WL_TRACE(("wl: wl_free\n"));
+ {
+ if (wl->dev && wl->dev->irq)
+ free_irq(wl->dev->irq, wl);
+ }
+
+#if defined(WL_CONFIG_RFKILL)
+ wl_uninit_rfkill(wl);
+#endif
+
+ if (wl->dev) {
+ wl_free_if(wl, WL_DEV_IF(wl->dev));
+ wl->dev = NULL;
+ }
+
+ tasklet_kill(&wl->tasklet);
+
+ tasklet_kill(&wl->tx_tasklet);
+
+ if (wl->pub) {
+ wlc_module_unregister(wl->pub, "linux", wl);
+ }
+
+ if (wl->wlc) {
+ {
+ char tmp1[128];
+ sprintf(tmp1, "%s%d", HYBRID_PROC, wl->pub->unit);
+ remove_proc_entry(tmp1, 0);
+ }
+ wlc_detach(wl->wlc);
+ wl->wlc = NULL;
+ wl->pub = NULL;
+ }
+
+ while (atomic_read(&wl->callbacks) > 0)
+ schedule();
+
+ for (t = wl->timers; t; t = next) {
+ next = t->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ }
+
+ osh = wl->osh;
+
+ if (wl->regsva && BUSTYPE(wl->bcm_bustype) != SDIO_BUS &&
+ BUSTYPE(wl->bcm_bustype) != JTAG_BUS) {
+ iounmap((void*)wl->regsva);
+ }
+ wl->regsva = NULL;
+
+ if (wl->bar1_addr) {
+ iounmap(wl->bar1_addr);
+ wl->bar1_addr = NULL;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#endif
+
+ wl_txq_free(wl);
+
+ MFREE(osh, wl, sizeof(wl_info_t));
+
+ if (MALLOCED(osh)) {
+ printf("Memory leak of bytes %d\n", MALLOCED(osh));
+#ifndef BCMDBG_MEM
+ ASSERT(0);
+#endif
+ }
+
+#ifdef BCMDBG_MEM
+
+ MALLOC_DUMP(osh, NULL);
+#endif
+
+ osl_detach(osh);
+}
+
+static int
+wl_open(struct net_device *dev)
+{
+ wl_info_t *wl;
+ int error = 0;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_open\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d: (%s): wl_open() -> wl_up()\n",
+ wl->pub->unit, wl->dev->name));
+
+ error = wl_up(wl);
+ if (!error) {
+ error = wlc_set(wl->wlc, WLC_SET_PROMISC, (dev->flags & IFF_PROMISC));
+ }
+ WL_UNLOCK(wl);
+
+ if (!error)
+ OLD_MOD_INC_USE_COUNT;
+
+#if defined(USE_CFG80211)
+ if (wl_cfg80211_up(dev)) {
+ WL_ERROR(("%s: failed to bring up cfg80211\n", __func__));
+ return -1;
+ }
+#endif
+ return (error? -ENODEV : 0);
+}
+
+static int
+wl_close(struct net_device *dev)
+{
+ wl_info_t *wl;
+
+ if (!dev)
+ return -ENETDOWN;
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_down(dev);
+#endif
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_close\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d (%s): wl_close() -> wl_down()\n",
+ wl->pub->unit, wl->dev->name));
+
+ if (wl->if_list == NULL) {
+ wl_down(wl);
+ }
+ WL_UNLOCK(wl);
+
+ OLD_MOD_DEC_USE_COUNT;
+
+ return (0);
+}
+
+void * BCMFASTPATH
+wl_get_ifctx(struct wl_info *wl, int ctx_id, wl_if_t *wlif)
+{
+ void *ifctx = NULL;
+
+ switch (ctx_id) {
+ case IFCTX_NETDEV:
+ ifctx = (void *)((wlif == NULL) ? wl->dev : wlif->dev);
+ break;
+
+ default:
+ break;
+ }
+
+ return ifctx;
+}
+
+static int BCMFASTPATH
+wl_start_int(wl_info_t *wl, wl_if_t *wlif, struct sk_buff *skb)
+{
+ void *pkt;
+
+ WL_TRACE(("wl%d: wl_start: len %d data_len %d summed %d csum: 0x%x\n",
+ wl->pub->unit, skb->len, skb->data_len, skb->ip_summed, (uint32)skb->csum));
+
+ WL_LOCK(wl);
+
+ pkt = PKTFRMNATIVE(wl->osh, skb);
+ ASSERT(pkt != NULL);
+
+ if (WME_ENAB(wl->pub) && (PKTPRIO(pkt) == 0))
+ pktsetprio(pkt, FALSE);
+
+ wlc_sendpkt(wl->wlc, pkt, wlif->wlcif);
+
+ WL_UNLOCK(wl);
+
+ return (0);
+}
+
+void
+wl_txflowcontrol(wl_info_t *wl, struct wl_if *wlif, bool state, int prio)
+{
+ struct net_device *dev;
+
+ ASSERT(prio == ALLPRIO);
+
+ if (wlif == NULL)
+ dev = wl->dev;
+ else if (!wlif->dev_registed)
+ return;
+ else
+ dev = wlif->dev;
+
+ if (state == ON)
+ netif_stop_queue(dev);
+ else
+ netif_wake_queue(dev);
+}
+
+static int
+wl_schedule_task(wl_info_t *wl, void (*fn)(struct wl_task *task), void *context)
+{
+ wl_task_t *task;
+
+ WL_TRACE(("wl%d: wl_schedule_task\n", wl->pub->unit));
+
+ if (!(task = MALLOC(wl->osh, sizeof(wl_task_t)))) {
+ WL_ERROR(("wl%d: wl_schedule_task: out of memory, malloced %d bytes\n",
+ wl->pub->unit, MALLOCED(wl->osh)));
+ return -ENOMEM;
+ }
+
+ MY_INIT_WORK(&task->work, (work_func_t)fn);
+ task->context = context;
+
+ if (!schedule_work(&task->work)) {
+ WL_ERROR(("wl%d: schedule_work() failed\n", wl->pub->unit));
+ MFREE(wl->osh, task, sizeof(wl_task_t));
+ return -ENOMEM;
+ }
+
+ atomic_inc(&wl->callbacks);
+
+ return 0;
+}
+
+static struct wl_if *
+wl_alloc_if(wl_info_t *wl, int iftype, uint subunit, struct wlc_if *wlcif)
+{
+ wl_if_t *wlif;
+ wl_if_t *p;
+
+ if (!(wlif = MALLOC(wl->osh, sizeof(wl_if_t)))) {
+ WL_ERROR(("wl%d: wl_alloc_if: out of memory, malloced %d bytes\n",
+ (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh)));
+ return NULL;
+ }
+ bzero(wlif, sizeof(wl_if_t));
+ wlif->wl = wl;
+ wlif->wlcif = wlcif;
+ wlif->subunit = subunit;
+ wlif->if_type = iftype;
+
+ if (wl->if_list == NULL)
+ wl->if_list = wlif;
+ else {
+ p = wl->if_list;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = wlif;
+ }
+
+ return wlif;
+}
+
+static void
+wl_free_if(wl_info_t *wl, wl_if_t *wlif)
+{
+ wl_if_t *p;
+ ASSERT(wlif);
+ ASSERT(wl);
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ if (wlif->dev_registed) {
+ ASSERT(wlif->dev);
+ unregister_netdev(wlif->dev);
+ wlif->dev_registed = FALSE;
+ }
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_detach(wlif->dev);
+#endif
+
+ p = wl->if_list;
+ if (p == wlif)
+ wl->if_list = p->next;
+ else {
+ while (p != NULL && p->next != wlif)
+ p = p->next;
+ if (p != NULL)
+ p->next = p->next->next;
+ }
+
+ if (wlif->dev) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+ MFREE(wl->osh, wlif->dev->priv, sizeof(priv_link_t));
+ MFREE(wl->osh, wlif->dev, sizeof(struct net_device));
+#else
+ free_netdev(wlif->dev);
+ wlif->dev = NULL;
+#endif
+ }
+
+ MFREE(wl->osh, wlif, sizeof(wl_if_t));
+}
+
+static struct net_device *
+wl_alloc_linux_if(wl_if_t *wlif)
+{
+ wl_info_t *wl = wlif->wl;
+ struct net_device *dev;
+ priv_link_t *priv_link;
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
+ dev = MALLOC(wl->osh, sizeof(struct net_device));
+ if (!dev) {
+ WL_ERROR(("wl%d: %s: malloc of net_device failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+ bzero(dev, sizeof(struct net_device));
+ ether_setup(dev);
+
+ strncpy(dev->name, intf_name, IFNAMSIZ-1);
+ dev->name[IFNAMSIZ-1] = '\0';
+
+ priv_link = MALLOC(wl->osh, sizeof(priv_link_t));
+ if (!priv_link) {
+ WL_ERROR(("wl%d: %s: malloc of priv_link failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ MFREE(wl->osh, dev, sizeof(struct net_device));
+ return NULL;
+ }
+ dev->priv = priv_link;
+#else
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
+ dev = alloc_netdev(sizeof(priv_link_t), intf_name, ether_setup);
+#else
+ dev = alloc_netdev(sizeof(priv_link_t), intf_name, NET_NAME_UNKNOWN, ether_setup);
+#endif
+
+ if (!dev) {
+ WL_ERROR(("wl%d: %s: alloc_netdev failed\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+ priv_link = netdev_priv(dev);
+ if (!priv_link) {
+ WL_ERROR(("wl%d: %s: cannot get netdev_priv\n",
+ (wl->pub)?wl->pub->unit:wlif->subunit, __FUNCTION__));
+ return NULL;
+ }
+#endif
+
+ priv_link->wlif = wlif;
+ wlif->dev = dev;
+
+ if (wlif->if_type != WL_IFTYPE_MON && wl->dev && netif_queue_stopped(wl->dev))
+ netif_stop_queue(dev);
+
+ return dev;
+}
+
+char *
+wl_ifname(wl_info_t *wl, wl_if_t *wlif)
+{
+ if (wlif) {
+ return wlif->name;
+ } else {
+ return wl->dev->name;
+ }
+}
+
+void
+wl_init(wl_info_t *wl)
+{
+ WL_TRACE(("wl%d: wl_init\n", wl->pub->unit));
+
+ wl_reset(wl);
+
+ wlc_init(wl->wlc);
+}
+
+uint
+wl_reset(wl_info_t *wl)
+{
+ uint32 macintmask;
+
+ WL_TRACE(("wl%d: wl_reset\n", wl->pub->unit));
+
+ macintmask = wl_intrsoff(wl);
+
+ wlc_reset(wl->wlc);
+
+ wl_intrsrestore(wl, macintmask);
+
+ wl->resched = 0;
+
+ return (0);
+}
+
+void BCMFASTPATH
+wl_intrson(wl_info_t *wl)
+{
+ unsigned long flags = 0;
+
+ INT_LOCK(wl, flags);
+ wlc_intrson(wl->wlc);
+ INT_UNLOCK(wl, flags);
+}
+
+bool
+wl_alloc_dma_resources(wl_info_t *wl, uint addrwidth)
+{
+ return TRUE;
+}
+
+uint32 BCMFASTPATH
+wl_intrsoff(wl_info_t *wl)
+{
+ unsigned long flags = 0;
+ uint32 status;
+
+ INT_LOCK(wl, flags);
+ status = wlc_intrsoff(wl->wlc);
+ INT_UNLOCK(wl, flags);
+ return status;
+}
+
+void
+wl_intrsrestore(wl_info_t *wl, uint32 macintmask)
+{
+ unsigned long flags = 0;
+
+ INT_LOCK(wl, flags);
+ wlc_intrsrestore(wl->wlc, macintmask);
+ INT_UNLOCK(wl, flags);
+}
+
+int
+wl_up(wl_info_t *wl)
+{
+ int error = 0;
+ wl_if_t *wlif;
+
+ WL_TRACE(("wl%d: wl_up\n", wl->pub->unit));
+
+ if (wl->pub->up)
+ return (0);
+
+ error = wlc_up(wl->wlc);
+
+ if (!error) {
+ for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) {
+ wl_txflowcontrol(wl, wlif, OFF, ALLPRIO);
+ }
+ }
+
+ return (error);
+}
+
+void
+wl_down(wl_info_t *wl)
+{
+ wl_if_t *wlif;
+ int monitor = 0;
+ uint callbacks, ret_val = 0;
+
+ WL_TRACE(("wl%d: wl_down\n", wl->pub->unit));
+
+ for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) {
+ if (wlif->dev) {
+ netif_down(wlif->dev);
+ netif_stop_queue(wlif->dev);
+ }
+ }
+
+ if (wl->monitor_dev) {
+ ret_val = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &monitor, sizeof(int), NULL);
+ if (ret_val != BCME_OK) {
+ WL_ERROR(("%s: Disabling MONITOR failed %d\n", __FUNCTION__, ret_val));
+ }
+ }
+
+ if (wl->wlc)
+ ret_val = wlc_down(wl->wlc);
+
+ callbacks = atomic_read(&wl->callbacks) - ret_val;
+ BCM_REFERENCE(callbacks);
+
+ WL_UNLOCK(wl);
+
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+ int i = 0;
+ for (i = 0; (atomic_read(&wl->callbacks) > callbacks) && i < 10000; i++) {
+ schedule();
+ flush_scheduled_work();
+ }
+ }
+ else
+ {
+
+ SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
+ }
+
+ WL_LOCK(wl);
+}
+
+static int
+wl_toe_get(wl_info_t *wl, uint32 *toe_ol)
+{
+ if (wlc_iovar_getint(wl->wlc, "toe_ol", toe_ol) != 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int
+wl_toe_set(wl_info_t *wl, uint32 toe_ol)
+{
+ if (wlc_iovar_setint(wl->wlc, "toe_ol", toe_ol) != 0)
+ return -EOPNOTSUPP;
+
+ if (wlc_iovar_setint(wl->wlc, "toe", (toe_ol != 0)) != 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static void
+wl_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ wl_info_t *wl = WL_INFO(dev);
+
+#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+ if (!wl || !wl->pub || !wl->wlc || !wl->dev)
+ return;
+#endif
+ bzero(info, sizeof(struct ethtool_drvinfo));
+ snprintf(info->driver, sizeof(info->driver), "wl%d", wl->pub->unit);
+ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version));
+ info->version[(sizeof(info->version))-1] = '\0';
+}
+
+static int
+wl_ethtool(wl_info_t *wl, void *uaddr, wl_if_t *wlif)
+{
+ struct ethtool_drvinfo info;
+ struct ethtool_value edata;
+ uint32 cmd;
+ uint32 toe_cmpnt = 0, csum_dir;
+ int ret;
+
+ if (!wl || !wl->pub || !wl->wlc)
+ return -ENODEV;
+
+ WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__));
+
+ if (copy_from_user(&cmd, uaddr, sizeof(uint32)))
+ return (-EFAULT);
+
+ switch (cmd) {
+ case ETHTOOL_GDRVINFO:
+ if (!wl->dev)
+ return -ENETDOWN;
+
+ wl_get_driver_info(wl->dev, &info);
+ info.cmd = cmd;
+ if (copy_to_user(uaddr, &info, sizeof(info)))
+ return (-EFAULT);
+ break;
+
+ case ETHTOOL_GRXCSUM:
+ case ETHTOOL_GTXCSUM:
+ if ((ret = wl_toe_get(wl, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ edata.cmd = cmd;
+ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
+
+ if (copy_to_user(uaddr, &edata, sizeof(edata)))
+ return (-EFAULT);
+ break;
+
+ case ETHTOOL_SRXCSUM:
+ case ETHTOOL_STXCSUM:
+ if (copy_from_user(&edata, uaddr, sizeof(edata)))
+ return (-EFAULT);
+
+ if ((ret = wl_toe_get(wl, &toe_cmpnt)) < 0)
+ return ret;
+
+ csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+
+ if (edata.data != 0)
+ toe_cmpnt |= csum_dir;
+ else
+ toe_cmpnt &= ~csum_dir;
+
+ if ((ret = wl_toe_set(wl, toe_cmpnt)) < 0)
+ return ret;
+
+ if (cmd == ETHTOOL_STXCSUM) {
+ if (!wl->dev)
+ return -ENETDOWN;
+ if (edata.data)
+ wl->dev->features |= NETIF_F_IP_CSUM;
+ else
+ wl->dev->features &= ~NETIF_F_IP_CSUM;
+ }
+
+ break;
+
+ default:
+ return (-EOPNOTSUPP);
+
+ }
+
+ return (0);
+}
+
+int
+wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ wl_info_t *wl;
+ wl_if_t *wlif;
+ void *buf = NULL;
+ wl_ioctl_t ioc;
+ int bcmerror;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+ wlif = WL_DEV_IF(dev);
+ if (wlif == NULL || wl == NULL || wl->dev == NULL)
+ return -ENETDOWN;
+
+ bcmerror = 0;
+
+ WL_TRACE(("wl%d: wl_ioctl: cmd 0x%x\n", wl->pub->unit, cmd));
+
+#ifdef USE_IW
+
+ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+
+ return wl_iw_ioctl(dev, ifr, cmd);
+ }
+#endif
+
+ if (cmd == SIOCETHTOOL)
+ return (wl_ethtool(wl, (void*)ifr->ifr_data, wlif));
+
+ switch (cmd) {
+ case SIOCDEVPRIVATE :
+ break;
+ default:
+ bcmerror = BCME_UNSUPPORTED;
+ goto done2;
+ }
+
+ if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+ bcmerror = BCME_BADADDR;
+ goto done2;
+ }
+
+ if (segment_eq(get_fs(), KERNEL_DS))
+ buf = ioc.buf;
+
+ else if (ioc.buf) {
+ if (!(buf = (void *) MALLOC(wl->osh, MAX(ioc.len, WLC_IOCTL_MAXLEN)))) {
+ bcmerror = BCME_NORESOURCE;
+ goto done2;
+ }
+
+ if (copy_from_user(buf, ioc.buf, ioc.len)) {
+ bcmerror = BCME_BADADDR;
+ goto done1;
+ }
+ }
+
+ WL_LOCK(wl);
+ if (!capable(CAP_NET_ADMIN)) {
+ bcmerror = BCME_EPERM;
+ } else {
+ bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif);
+ }
+ WL_UNLOCK(wl);
+
+done1:
+ if (ioc.buf && (ioc.buf != buf)) {
+ if (copy_to_user(ioc.buf, buf, ioc.len))
+ bcmerror = BCME_BADADDR;
+ MFREE(wl->osh, buf, MAX(ioc.len, WLC_IOCTL_MAXLEN));
+ }
+
+done2:
+ ASSERT(VALID_BCMERROR(bcmerror));
+ if (bcmerror != 0)
+ wl->pub->bcmerror = bcmerror;
+ return (OSL_ERROR(bcmerror));
+}
+
+static struct net_device_stats*
+wl_get_stats(struct net_device *dev)
+{
+ struct net_device_stats *stats_watchdog = NULL;
+ struct net_device_stats *stats = NULL;
+ wl_info_t *wl;
+ wl_if_t *wlif;
+
+ if (!dev)
+ return NULL;
+
+ if ((wl = WL_INFO(dev)) == NULL)
+ return NULL;
+
+ if ((wlif = WL_DEV_IF(dev)) == NULL)
+ return NULL;
+
+ if ((stats = &wlif->stats) == NULL)
+ return NULL;
+
+ WL_TRACE(("wl%d: wl_get_stats\n", wl->pub->unit));
+
+ ASSERT(wlif->stats_id < 2);
+ stats_watchdog = &wlif->stats_watchdog[wlif->stats_id];
+ memcpy(stats, stats_watchdog, sizeof(struct net_device_stats));
+ return (stats);
+}
+
+#ifdef USE_IW
+struct iw_statistics *
+wl_get_wireless_stats(struct net_device *dev)
+{
+ int res = 0;
+ wl_info_t *wl;
+ wl_if_t *wlif;
+ struct iw_statistics *wstats = NULL;
+ struct iw_statistics *wstats_watchdog = NULL;
+ int phy_noise, rssi;
+
+ if (!dev)
+ return NULL;
+
+ if ((wl = WL_INFO(dev)) == NULL)
+ return NULL;
+
+ if ((wlif = WL_DEV_IF(dev)) == NULL)
+ return NULL;
+
+ if ((wstats = &wlif->wstats) == NULL)
+ return NULL;
+
+ WL_TRACE(("wl%d: wl_get_wireless_stats\n", wl->pub->unit));
+
+ ASSERT(wlif->stats_id < 2);
+ wstats_watchdog = &wlif->wstats_watchdog[wlif->stats_id];
+
+ phy_noise = wlif->phy_noise;
+#if WIRELESS_EXT > 11
+ wstats->discard.nwid = 0;
+ wstats->discard.code = wstats_watchdog->discard.code;
+ wstats->discard.fragment = wstats_watchdog->discard.fragment;
+ wstats->discard.retries = wstats_watchdog->discard.retries;
+ wstats->discard.misc = wstats_watchdog->discard.misc;
+
+ wstats->miss.beacon = 0;
+#endif
+
+ if (AP_ENAB(wl->pub))
+ rssi = 0;
+ else {
+ scb_val_t scb;
+ res = wlc_ioctl(wl->wlc, WLC_GET_RSSI, &scb, sizeof(int), wlif->wlcif);
+ if (res) {
+ WL_ERROR(("wl%d: %s: WLC_GET_RSSI failed (%d)\n",
+ wl->pub->unit, __FUNCTION__, res));
+ return NULL;
+ }
+ rssi = scb.val;
+ }
+
+ if (rssi <= WLC_RSSI_NO_SIGNAL)
+ wstats->qual.qual = 0;
+ else if (rssi <= WLC_RSSI_VERY_LOW)
+ wstats->qual.qual = 1;
+ else if (rssi <= WLC_RSSI_LOW)
+ wstats->qual.qual = 2;
+ else if (rssi <= WLC_RSSI_GOOD)
+ wstats->qual.qual = 3;
+ else if (rssi <= WLC_RSSI_VERY_GOOD)
+ wstats->qual.qual = 4;
+ else
+ wstats->qual.qual = 5;
+
+ wstats->qual.level = 0x100 + rssi;
+ wstats->qual.noise = 0x100 + phy_noise;
+#if WIRELESS_EXT > 18
+ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
+#else
+ wstats->qual.updated |= 7;
+#endif
+
+ return wstats;
+}
+#endif
+
+static int
+wl_set_mac_address(struct net_device *dev, void *addr)
+{
+ int err = 0;
+ wl_info_t *wl;
+ struct sockaddr *sa = (struct sockaddr *) addr;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_set_mac_address\n", wl->pub->unit));
+
+ WL_LOCK(wl);
+
+ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN);
+ err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, sa->sa_data, ETHER_ADDR_LEN,
+ IOV_SET, (WL_DEV_IF(dev))->wlcif);
+ WL_UNLOCK(wl);
+ if (err)
+ WL_ERROR(("wl%d: wl_set_mac_address: error setting MAC addr override\n",
+ wl->pub->unit));
+ return err;
+}
+
+static void
+wl_set_multicast_list(struct net_device *dev)
+{
+ if (!WL_ALL_PASSIVE_ENAB((wl_info_t *)WL_INFO(dev)))
+ _wl_set_multicast_list(dev);
+ else {
+ wl_info_t *wl = WL_INFO(dev);
+ wl->multicast_task.context = dev;
+
+ if (schedule_work(&wl->multicast_task.work)) {
+
+ atomic_inc(&wl->callbacks);
+ }
+ }
+}
+
+static void
+_wl_set_multicast_list(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+ struct dev_mc_list *mclist;
+#else
+ struct netdev_hw_addr *ha;
+#endif
+ wl_info_t *wl;
+ int i, buflen;
+ struct maclist *maclist;
+ int allmulti;
+
+ if (!dev)
+ return;
+ wl = WL_INFO(dev);
+
+ WL_TRACE(("wl%d: wl_set_multicast_list\n", wl->pub->unit));
+
+ if (wl->pub->up) {
+ allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: FALSE;
+
+ buflen = sizeof(struct maclist) + (MAXMULTILIST * ETHER_ADDR_LEN);
+
+ if ((maclist = MALLOC(wl->pub->osh, buflen)) == NULL) {
+ return;
+ }
+
+ i = 0;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+ for (mclist = dev->mc_list; mclist && (i < dev->mc_count); mclist = mclist->next) {
+ if (i >= MAXMULTILIST) {
+ allmulti = TRUE;
+ i = 0;
+ break;
+ }
+ bcopy(mclist->dmi_addr, &maclist->ea[i++], ETHER_ADDR_LEN);
+ }
+#else
+ netdev_for_each_mc_addr(ha, dev) {
+ if (i >= MAXMULTILIST) {
+ allmulti = TRUE;
+ i = 0;
+ break;
+ }
+ bcopy(ha->addr, &maclist->ea[i++], ETHER_ADDR_LEN);
+ }
+#endif
+ maclist->count = i;
+
+ WL_LOCK(wl);
+
+ wlc_iovar_op(wl->wlc, "allmulti", NULL, 0, &allmulti, sizeof(allmulti), IOV_SET,
+ (WL_DEV_IF(dev))->wlcif);
+ wlc_set(wl->wlc, WLC_SET_PROMISC, (dev->flags & IFF_PROMISC));
+
+ wlc_iovar_op(wl->wlc, "mcast_list", NULL, 0, maclist, buflen, IOV_SET,
+ (WL_DEV_IF(dev))->wlcif);
+
+ WL_UNLOCK(wl);
+ MFREE(wl->pub->osh, maclist, buflen);
+ }
+
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+irqreturn_t BCMFASTPATH
+wl_isr(int irq, void *dev_id)
+#else
+irqreturn_t BCMFASTPATH
+wl_isr(int irq, void *dev_id, struct pt_regs *ptregs)
+#endif
+{
+ wl_info_t *wl;
+ bool ours, wantdpc;
+ unsigned long flags;
+
+ wl = (wl_info_t*) dev_id;
+
+ WL_ISRLOCK(wl, flags);
+
+ if ((ours = wlc_isr(wl->wlc, &wantdpc))) {
+
+ if (wantdpc) {
+
+ ASSERT(wl->resched == FALSE);
+ if (WL_ALL_PASSIVE_ENAB(wl)) {
+ if (schedule_work(&wl->wl_dpc_task.work))
+ atomic_inc(&wl->callbacks);
+ else
+ ASSERT(0);
+ } else
+ tasklet_schedule(&wl->tasklet);
+ }
+ }
+
+ WL_ISRUNLOCK(wl, flags);
+
+ return IRQ_RETVAL(ours);
+}
+
+static void BCMFASTPATH
+wl_dpc(ulong data)
+{
+ wl_info_t *wl;
+
+ wl = (wl_info_t *)data;
+
+ WL_LOCK(wl);
+
+ if (wl->pub->up) {
+ wlc_dpc_info_t dpci = {0};
+
+ if (wl->resched) {
+ unsigned long flags = 0;
+ INT_LOCK(wl, flags);
+ wlc_intrsupd(wl->wlc);
+ INT_UNLOCK(wl, flags);
+ }
+
+ wl->resched = wlc_dpc(wl->wlc, TRUE, &dpci);
+
+ wl->processed = dpci.processed;
+ }
+
+ if (!wl->pub->up) {
+
+ if ((WL_ALL_PASSIVE_ENAB(wl))) {
+ atomic_dec(&wl->callbacks);
+ }
+ goto done;
+ }
+
+ if (wl->resched) {
+ if (!(WL_ALL_PASSIVE_ENAB(wl)))
+ tasklet_schedule(&wl->tasklet);
+ else
+ if (!schedule_work(&wl->wl_dpc_task.work)) {
+
+ ASSERT(0);
+ }
+ }
+ else {
+
+ if (WL_ALL_PASSIVE_ENAB(wl))
+ atomic_dec(&wl->callbacks);
+ wl_intrson(wl);
+ }
+
+done:
+ WL_UNLOCK(wl);
+ return;
+}
+
+static void BCMFASTPATH
+wl_dpc_rxwork(struct wl_task *task)
+{
+ wl_info_t *wl = (wl_info_t *)task->context;
+ WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__));
+
+ wl_dpc((unsigned long)wl);
+ return;
+}
+
+void BCMFASTPATH
+wl_sendup(wl_info_t *wl, wl_if_t *wlif, void *p, int numpkt)
+{
+ struct sk_buff *skb;
+ bool brcm_specialpkt;
+
+ WL_TRACE(("wl%d: wl_sendup: %d bytes\n", wl->pub->unit, PKTLEN(wl->osh, p)));
+
+ brcm_specialpkt =
+ (ntoh16_ua(PKTDATA(wl->pub->osh, p) + ETHER_TYPE_OFFSET) == ETHER_TYPE_BRCM);
+
+ if (!brcm_specialpkt) {
+
+ }
+
+ if (wlif) {
+
+ if (!wlif->dev || !netif_device_present(wlif->dev)) {
+ WL_ERROR(("wl%d: wl_sendup: interface not ready\n", wl->pub->unit));
+ PKTFREE(wl->osh, p, FALSE);
+ return;
+ }
+
+ skb = PKTTONATIVE(wl->osh, p);
+ skb->dev = wlif->dev;
+ } else {
+
+ skb = PKTTONATIVE(wl->osh, p);
+ skb->dev = wl->dev;
+
+ }
+
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ if (!brcm_specialpkt && !ISALIGNED(skb->data, 4)) {
+ WL_ERROR(("Unaligned assert. skb %p. skb->data %p.\n", skb, skb->data));
+ if (wlif) {
+ WL_ERROR(("wl_sendup: dev name is %s (wlif) \n", wlif->dev->name));
+ WL_ERROR(("wl_sendup: hard header len %d (wlif) \n",
+ wlif->dev->hard_header_len));
+ }
+ WL_ERROR(("wl_sendup: dev name is %s (wl) \n", wl->dev->name));
+ WL_ERROR(("wl_sendup: hard header len %d (wl) \n", wl->dev->hard_header_len));
+ ASSERT(ISALIGNED(skb->data, 4));
+ }
+
+ WL_APSTA_RX(("wl%d: wl_sendup(): pkt %p summed %d on interface %p (%s)\n",
+ wl->pub->unit, p, skb->ip_summed, wlif, skb->dev->name));
+
+ netif_rx(skb);
+
+}
+
+int
+wl_osl_pcie_rc(struct wl_info *wl, uint op, int param)
+{
+ return 0;
+}
+
+void
+wl_dump_ver(wl_info_t *wl, struct bcmstrbuf *b)
+{
+ bcm_bprintf(b, "wl%d: %s %s version %s\n", wl->pub->unit,
+ __DATE__, __TIME__, EPI_VERSION_STR);
+}
+
+#if defined(BCMDBG)
+static int
+wl_dump(wl_info_t *wl, struct bcmstrbuf *b)
+{
+ wl_if_t *p;
+ int i;
+
+ wl_dump_ver(wl, b);
+
+ bcm_bprintf(b, "name %s dev %p tbusy %d callbacks %d malloced %d\n",
+ wl->dev->name, wl->dev, (uint)netif_queue_stopped(wl->dev),
+ atomic_read(&wl->callbacks), MALLOCED(wl->osh));
+
+ p = wl->if_list;
+ if (p)
+ p = p->next;
+ for (i = 0; p != NULL; p = p->next, i++) {
+ if ((i % 4) == 0) {
+ if (i != 0)
+ bcm_bprintf(b, "\n");
+ bcm_bprintf(b, "Interfaces:");
+ }
+ bcm_bprintf(b, " name %s dev %p", p->dev->name, p->dev);
+ }
+ if (i)
+ bcm_bprintf(b, "\n");
+
+ return 0;
+}
+#endif
+
+static void
+wl_link_up(wl_info_t *wl, char *ifname)
+{
+ WL_ERROR(("wl%d: link up (%s)\n", wl->pub->unit, ifname));
+}
+
+static void
+wl_link_down(wl_info_t *wl, char *ifname)
+{
+ WL_ERROR(("wl%d: link down (%s)\n", wl->pub->unit, ifname));
+}
+
+void
+wl_event(wl_info_t *wl, char *ifname, wlc_event_t *e)
+{
+#ifdef USE_IW
+ wl_iw_event(wl->dev, &(e->event), e->data);
+#endif
+
+#if defined(USE_CFG80211)
+ wl_cfg80211_event(wl->dev, &(e->event), e->data);
+#endif
+ switch (e->event.event_type) {
+ case WLC_E_LINK:
+ case WLC_E_NDIS_LINK:
+ if (e->event.flags&WLC_EVENT_MSG_LINK)
+ wl_link_up(wl, ifname);
+ else
+ wl_link_down(wl, ifname);
+ break;
+#if defined(WL_CONFIG_RFKILL)
+ case WLC_E_RADIO: {
+ mbool i;
+ if (wlc_get(wl->wlc, WLC_GET_RADIO, &i) < 0)
+ WL_ERROR(("%s: WLC_GET_RADIO failed\n", __FUNCTION__));
+ if (wl->last_phyind == (mbool)(i & WL_RADIO_HW_DISABLE))
+ break;
+
+ wl->last_phyind = (mbool)(i & WL_RADIO_HW_DISABLE);
+
+ WL_ERROR(("wl%d: Radio hardware state changed to %d\n", wl->pub->unit, i));
+ wl_report_radio_state(wl);
+ break;
+ }
+#else
+ case WLC_E_RADIO:
+ break;
+#endif
+ }
+}
+
+void
+wl_event_sync(wl_info_t *wl, char *ifname, wlc_event_t *e)
+{
+}
+
+static void BCMFASTPATH
+wl_sched_tx_tasklet(void *t)
+{
+ wl_info_t *wl = (wl_info_t *)t;
+ tasklet_schedule(&wl->tx_tasklet);
+}
+
+#define WL_CONFIG_SMP() FALSE
+
+static int BCMFASTPATH
+wl_start(struct sk_buff *skb, struct net_device *dev)
+{
+ wl_if_t *wlif;
+ wl_info_t *wl;
+
+ if (!dev)
+ return -ENETDOWN;
+
+ wlif = WL_DEV_IF(dev);
+ wl = WL_INFO(dev);
+
+ if (WL_ALL_PASSIVE_ENAB(wl) || (WL_RTR() && WL_CONFIG_SMP())) {
+ skb->prev = NULL;
+
+ TXQ_LOCK(wl);
+
+ if ((wl_txq_thresh > 0) && (wl->txq_cnt >= wl_txq_thresh)) {
+ PKTFRMNATIVE(wl->osh, skb);
+ PKTCFREE(wl->osh, skb, TRUE);
+ TXQ_UNLOCK(wl);
+ return 0;
+ }
+
+ if (wl->txq_head == NULL)
+ wl->txq_head = skb;
+ else
+ wl->txq_tail->prev = skb;
+ wl->txq_tail = skb;
+ wl->txq_cnt++;
+
+ if (!wl->txq_dispatched) {
+ int32 err = 0;
+
+ if (!WL_ALL_PASSIVE_ENAB(wl))
+ wl_sched_tx_tasklet(wl);
+ else
+ err = (int32)(schedule_work(&wl->txq_task.work) == 0);
+
+ if (!err) {
+ atomic_inc(&wl->callbacks);
+ wl->txq_dispatched = TRUE;
+ } else
+ WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
+ wl->pub->unit));
+ }
+
+ TXQ_UNLOCK(wl);
+ } else
+ return wl_start_int(wl, wlif, skb);
+
+ return (0);
+}
+
+static void BCMFASTPATH
+wl_start_txqwork(wl_task_t *task)
+{
+ wl_info_t *wl = (wl_info_t *)task->context;
+ struct sk_buff *skb;
+
+ WL_TRACE(("wl%d: %s txq_cnt %d\n", wl->pub->unit, __FUNCTION__, wl->txq_cnt));
+
+#ifdef BCMDBG
+ if (wl->txq_cnt >= 500)
+ WL_ERROR(("wl%d: WARNING dispatching over 500 packets in txqwork(%d)\n",
+ wl->pub->unit, wl->txq_cnt));
+#endif
+
+ TXQ_LOCK(wl);
+ while (wl->txq_head) {
+ skb = wl->txq_head;
+ wl->txq_head = skb->prev;
+ skb->prev = NULL;
+ if (wl->txq_head == NULL)
+ wl->txq_tail = NULL;
+ wl->txq_cnt--;
+ TXQ_UNLOCK(wl);
+
+ wl_start_int(wl, WL_DEV_IF(skb->dev), skb);
+
+ TXQ_LOCK(wl);
+ }
+
+ wl->txq_dispatched = FALSE;
+ atomic_dec(&wl->callbacks);
+ TXQ_UNLOCK(wl);
+
+ return;
+}
+
+static void BCMFASTPATH
+wl_tx_tasklet(ulong data)
+{
+ wl_task_t task;
+ task.context = (void *)data;
+ wl_start_txqwork(&task);
+}
+
+static void
+wl_txq_free(wl_info_t *wl)
+{
+ struct sk_buff *skb;
+
+ if (wl->txq_head == NULL) {
+ ASSERT(wl->txq_tail == NULL);
+ return;
+ }
+
+ while (wl->txq_head) {
+ skb = wl->txq_head;
+ wl->txq_head = skb->prev;
+ wl->txq_cnt--;
+ PKTFRMNATIVE(wl->osh, skb);
+ PKTCFREE(wl->osh, skb, TRUE);
+ }
+
+ wl->txq_tail = NULL;
+}
+
+static void
+wl_set_multicast_list_workitem(struct work_struct *work)
+{
+ wl_task_t *task = (wl_task_t *)work;
+ struct net_device *dev = (struct net_device*)task->context;
+ wl_info_t *wl;
+
+ wl = WL_INFO(dev);
+
+ atomic_dec(&wl->callbacks);
+
+ _wl_set_multicast_list(dev);
+}
+
+static void
+wl_timer_task(wl_task_t *task)
+{
+ wl_timer_t *t = (wl_timer_t *)task->context;
+
+ _wl_timer(t);
+ MFREE(t->wl->osh, task, sizeof(wl_task_t));
+
+ atomic_dec(&t->wl->callbacks);
+}
+
+static void
+wl_timer(ulong data)
+{
+ wl_timer_t *t = (wl_timer_t *)data;
+
+ if (!WL_ALL_PASSIVE_ENAB(t->wl))
+ _wl_timer(t);
+ else
+ wl_schedule_task(t->wl, wl_timer_task, t);
+}
+
+static void
+_wl_timer(wl_timer_t *t)
+{
+ wl_info_t *wl = t->wl;
+
+ WL_LOCK(wl);
+
+ if (t->set && (!timer_pending(&t->timer))) {
+ if (t->periodic) {
+ t->timer.expires = jiffies + t->ms*HZ/1000;
+ atomic_inc(&wl->callbacks);
+ add_timer(&t->timer);
+ t->set = TRUE;
+ } else
+ t->set = FALSE;
+
+ t->fn(t->arg);
+#ifdef BCMDBG
+ wlc_update_perf_stats(wl->wlc, WLC_PERF_STATS_TMR_DPC);
+ t->ticks++;
+#endif
+
+ }
+
+ atomic_dec(&wl->callbacks);
+
+ WL_UNLOCK(wl);
+}
+
+wl_timer_t *
+wl_init_timer(wl_info_t *wl, void (*fn)(void *arg), void *arg, const char *tname)
+{
+ wl_timer_t *t;
+
+ t = (wl_timer_t*)MALLOC(wl->osh, sizeof(wl_timer_t));
+
+ if (t == NULL) {
+ WL_ERROR(("wl%d: wl_init_timer: out of memory, malloced %d bytes\n",
+ wl->unit, MALLOCED(wl->osh)));
+ return 0;
+ }
+
+ bzero(t, sizeof(wl_timer_t));
+
+ init_timer(&t->timer);
+ t->timer.data = (ulong) t;
+ t->timer.function = wl_timer;
+ t->wl = wl;
+ t->fn = fn;
+ t->arg = arg;
+ t->next = wl->timers;
+ wl->timers = t;
+
+#ifdef BCMDBG
+ if ((t->name = MALLOC(wl->osh, strlen(tname) + 1)))
+ strcpy(t->name, tname);
+#endif
+
+ return t;
+}
+
+void
+wl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic)
+{
+#ifdef BCMDBG
+ if (t->set) {
+ WL_ERROR(("%s: Already set. Name: %s, per %d\n",
+ __FUNCTION__, t->name, periodic));
+ }
+#endif
+
+ t->ms = ms;
+ t->periodic = (bool) periodic;
+
+ if (t->set)
+ return;
+
+ t->set = TRUE;
+ t->timer.expires = jiffies + ms*HZ/1000;
+
+ atomic_inc(&wl->callbacks);
+ add_timer(&t->timer);
+}
+
+bool
+wl_del_timer(wl_info_t *wl, wl_timer_t *t)
+{
+ ASSERT(t);
+ if (t->set) {
+ t->set = FALSE;
+ if (!del_timer(&t->timer)) {
+#ifdef BCMDBG
+ WL_INFORM(("wl%d: Failed to delete timer %s\n", wl->unit, t->name));
+#endif
+ return TRUE;
+ }
+ atomic_dec(&wl->callbacks);
+ }
+
+ return TRUE;
+}
+
+void
+wl_free_timer(wl_info_t *wl, wl_timer_t *t)
+{
+ wl_timer_t *tmp;
+
+ wl_del_timer(wl, t);
+
+ if (wl->timers == t) {
+ wl->timers = wl->timers->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ return;
+
+ }
+
+ tmp = wl->timers;
+ while (tmp) {
+ if (tmp->next == t) {
+ tmp->next = t->next;
+#ifdef BCMDBG
+ if (t->name)
+ MFREE(wl->osh, t->name, strlen(t->name) + 1);
+#endif
+ MFREE(wl->osh, t, sizeof(wl_timer_t));
+ return;
+ }
+ tmp = tmp->next;
+ }
+
+}
+
+void
+wl_monitor(wl_info_t *wl, wl_rxsts_t *rxsts, void *p)
+{
+ struct sk_buff *oskb = (struct sk_buff *)p;
+ struct sk_buff *skb;
+ uchar *pdata;
+ uint len;
+
+ len = 0;
+ skb = NULL;
+ WL_TRACE(("wl%d: wl_monitor\n", wl->pub->unit));
+
+ if (!wl->monitor_dev)
+ return;
+
+ if (wl->monitor_type == 1) {
+ p80211msg_t *phdr;
+
+ len = sizeof(p80211msg_t) + oskb->len - D11_PHY_HDR_LEN;
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 1", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+ phdr = (p80211msg_t*)skb->data;
+
+ phdr->msgcode = WL_MON_FRAME;
+ phdr->msglen = sizeof(p80211msg_t);
+ strcpy(phdr->devname, wl->dev->name);
+
+ phdr->hosttime.did = WL_MON_FRAME_HOSTTIME;
+ phdr->hosttime.status = P80211ITEM_OK;
+ phdr->hosttime.len = 4;
+ phdr->hosttime.data = jiffies;
+
+ phdr->channel.did = WL_MON_FRAME_CHANNEL;
+ phdr->channel.status = P80211ITEM_NO_VALUE;
+ phdr->channel.len = 4;
+ phdr->channel.data = 0;
+
+ phdr->signal.did = WL_MON_FRAME_SIGNAL;
+ phdr->signal.status = P80211ITEM_OK;
+ phdr->signal.len = 4;
+
+ phdr->signal.data = rxsts->preamble;
+
+ phdr->noise.did = WL_MON_FRAME_NOISE;
+ phdr->noise.status = P80211ITEM_NO_VALUE;
+ phdr->noise.len = 4;
+ phdr->noise.data = 0;
+
+ phdr->rate.did = WL_MON_FRAME_RATE;
+ phdr->rate.status = P80211ITEM_OK;
+ phdr->rate.len = 4;
+ phdr->rate.data = rxsts->datarate;
+
+ phdr->istx.did = WL_MON_FRAME_ISTX;
+ phdr->istx.status = P80211ITEM_NO_VALUE;
+ phdr->istx.len = 4;
+ phdr->istx.data = 0;
+
+ phdr->mactime.did = WL_MON_FRAME_MACTIME;
+ phdr->mactime.status = P80211ITEM_OK;
+ phdr->mactime.len = 4;
+ phdr->mactime.data = rxsts->mactime;
+
+ phdr->rssi.did = WL_MON_FRAME_RSSI;
+ phdr->rssi.status = P80211ITEM_OK;
+ phdr->rssi.len = 4;
+ phdr->rssi.data = rxsts->signal;
+
+ phdr->sq.did = WL_MON_FRAME_SQ;
+ phdr->sq.status = P80211ITEM_OK;
+ phdr->sq.len = 4;
+ phdr->sq.data = rxsts->sq;
+
+ phdr->frmlen.did = WL_MON_FRAME_FRMLEN;
+ phdr->frmlen.status = P80211ITEM_OK;
+ phdr->frmlen.status = P80211ITEM_OK;
+ phdr->frmlen.len = 4;
+ phdr->frmlen.data = rxsts->pktlength;
+
+ pdata = skb->data + sizeof(p80211msg_t);
+ bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
+
+ }
+ else if (wl->monitor_type == 2) {
+ int channel_frequency;
+ uint16 channel_flags;
+ uint8 flags;
+ uint16 rtap_len;
+ struct dot11_header *mac_header;
+ uint16 fc;
+
+ if (rxsts->phytype != WL_RXS_PHY_N)
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ else
+ rtap_len = sizeof(wl_radiotap_ht_brcm_2_t);
+
+ len = rtap_len + (oskb->len - D11_PHY_HDR_LEN);
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 2", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+
+ if (CHSPEC_IS2G(rxsts->chanspec)) {
+ channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_2_4_G);
+ } else {
+ channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_5_G);
+ }
+
+ mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN);
+ fc = ltoh16(mac_header->fc);
+
+ flags = IEEE80211_RADIOTAP_F_FCS;
+
+ if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT)
+ flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ if (fc & FC_WEP)
+ flags |= IEEE80211_RADIOTAP_F_WEP;
+
+ if (fc & FC_MOREFRAG)
+ flags |= IEEE80211_RADIOTAP_F_FRAG;
+
+ if (rxsts->pkterror & WL_RXS_CRC_ERROR)
+ flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+ if (rxsts->phytype != WL_RXS_PHY_N) {
+ wl_radiotap_legacy_t *rtl = (wl_radiotap_legacy_t *)skb->data;
+
+ rtl->ieee_radiotap.it_version = 0;
+ rtl->ieee_radiotap.it_pad = 0;
+ rtl->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY);
+
+ rtl->tsft_l = htol32(rxsts->mactime);
+ rtl->tsft_h = 0;
+ rtl->flags = flags;
+ rtl->rate = rxsts->datarate;
+ rtl->channel_freq = HTOL16(channel_frequency);
+ rtl->channel_flags = HTOL16(channel_flags);
+ rtl->signal = (int8)rxsts->signal;
+ rtl->noise = (int8)rxsts->noise;
+ rtl->antenna = rxsts->antenna;
+
+ memcpy(rtl->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtl->vend_skip_len = WL_RADIOTAP_LEGACY_SKIP_LEN;
+ rtl->vend_sns = 0;
+
+ memset(&rtl->nonht_vht, 0, sizeof(rtl->nonht_vht));
+ rtl->nonht_vht.len = WL_RADIOTAP_NONHT_VHT_LEN;
+ } else {
+ wl_radiotap_ht_brcm_2_t *rtht = (wl_radiotap_ht_brcm_2_t *)skb->data;
+
+ rtht->ieee_radiotap.it_version = 0;
+ rtht->ieee_radiotap.it_pad = 0;
+ rtht->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT_BRCM2);
+ rtht->it_present_ext = HTOL32(WL_RADIOTAP_BRCM2_HT_MCS);
+ rtht->pad1 = 0;
+
+ rtht->tsft_l = htol32(rxsts->mactime);
+ rtht->tsft_h = 0;
+ rtht->flags = flags;
+ rtht->pad2 = 0;
+ rtht->channel_freq = HTOL16(channel_frequency);
+ rtht->channel_flags = HTOL16(channel_flags);
+ rtht->signal = (int8)rxsts->signal;
+ rtht->noise = (int8)rxsts->noise;
+ rtht->antenna = rxsts->antenna;
+ rtht->pad3 = 0;
+
+ memcpy(rtht->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtht->vend_sns = WL_RADIOTAP_BRCM2_HT_SNS;
+ rtht->vend_skip_len = WL_RADIOTAP_HT_BRCM2_SKIP_LEN;
+ rtht->mcs = rxsts->mcs;
+ rtht->htflags = 0;
+ if (rxsts->htflags & WL_RXS_HTF_40)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_40;
+ if (rxsts->htflags & WL_RXS_HTF_SGI)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_SGI;
+ if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_GF;
+ if (rxsts->htflags & WL_RXS_HTF_LDPC)
+ rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_LDPC;
+ rtht->htflags |=
+ (rxsts->htflags & WL_RXS_HTF_STBC_MASK) <<
+ IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT;
+ }
+
+ pdata = skb->data + rtap_len;
+ bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
+ }
+ else if (wl->monitor_type == 3) {
+ int channel_frequency;
+ uint16 channel_flags;
+ uint8 flags;
+ uint16 rtap_len;
+ struct dot11_header * mac_header;
+ uint16 fc;
+
+ if (rxsts->phytype == WL_RXS_PHY_N) {
+ if (rxsts->encoding == WL_RXS_ENCODING_HT)
+ rtap_len = sizeof(wl_radiotap_ht_t);
+ else if (rxsts->encoding == WL_RXS_ENCODING_VHT)
+ rtap_len = sizeof(wl_radiotap_vht_t);
+ else
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ } else {
+ rtap_len = sizeof(wl_radiotap_legacy_t);
+ }
+
+ len = rtap_len + (oskb->len - D11_PHY_HDR_LEN);
+
+ if (oskb->next) {
+ struct sk_buff *amsdu_p = oskb->next;
+ uint amsdu_len = 0;
+ while (amsdu_p) {
+ amsdu_len += amsdu_p->len;
+ amsdu_p = amsdu_p->next;
+ }
+ len += amsdu_len;
+ }
+
+ if ((skb = dev_alloc_skb(len)) == NULL) {
+ WL_ERROR(("%s: dev_alloc_skb() failure, mon type 3", __FUNCTION__));
+ return;
+ }
+
+ skb_put(skb, len);
+
+ if (CHSPEC_IS2G(rxsts->chanspec)) {
+ channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_2_4_G);
+ } else {
+ channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM;
+ channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec),
+ WF_CHAN_FACTOR_5_G);
+ }
+
+ mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN);
+ fc = ltoh16(mac_header->fc);
+
+ flags = IEEE80211_RADIOTAP_F_FCS;
+
+ if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT)
+ flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ if (fc & FC_WEP)
+ flags |= IEEE80211_RADIOTAP_F_WEP;
+
+ if (fc & FC_MOREFRAG)
+ flags |= IEEE80211_RADIOTAP_F_FRAG;
+
+ if (rxsts->pkterror & WL_RXS_CRC_ERROR)
+ flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+ if ((rxsts->phytype != WL_RXS_PHY_N) ||
+ ((rxsts->encoding != WL_RXS_ENCODING_HT) &&
+ (rxsts->encoding != WL_RXS_ENCODING_VHT))) {
+ wl_radiotap_legacy_t *rtl = (wl_radiotap_legacy_t *)skb->data;
+
+ rtl->ieee_radiotap.it_version = 0;
+ rtl->ieee_radiotap.it_pad = 0;
+ rtl->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY);
+
+ rtl->it_present_ext = HTOL32(WL_RADIOTAP_LEGACY_VHT);
+ rtl->tsft_l = htol32(rxsts->mactime);
+ rtl->tsft_h = 0;
+ rtl->flags = flags;
+ rtl->rate = rxsts->datarate;
+ rtl->channel_freq = HTOL16(channel_frequency);
+ rtl->channel_flags = HTOL16(channel_flags);
+ rtl->signal = (int8)rxsts->signal;
+ rtl->noise = (int8)rxsts->noise;
+ rtl->antenna = rxsts->antenna;
+
+ memcpy(rtl->vend_oui, brcm_oui, sizeof(brcm_oui));
+ rtl->vend_skip_len = WL_RADIOTAP_LEGACY_SKIP_LEN;
+ rtl->vend_sns = 0;
+
+ memset(&rtl->nonht_vht, 0, sizeof(rtl->nonht_vht));
+ rtl->nonht_vht.len = WL_RADIOTAP_NONHT_VHT_LEN;
+ if (((fc & FC_KIND_MASK) == FC_RTS) ||
+ ((fc & FC_KIND_MASK) == FC_CTS)) {
+ rtl->nonht_vht.flags |= WL_RADIOTAP_F_NONHT_VHT_BW;
+ rtl->nonht_vht.bw = rxsts->bw_nonht;
+ rtl->vend_sns = WL_RADIOTAP_LEGACY_SNS;
+
+ }
+ if ((fc & FC_KIND_MASK) == FC_RTS) {
+ if (rxsts->vhtflags & WL_RXS_VHTF_DYN_BW_NONHT)
+ rtl->nonht_vht.flags
+ |= WL_RADIOTAP_F_NONHT_VHT_DYN_BW;
+ }
+ }
+ else if (rxsts->encoding == WL_RXS_ENCODING_VHT) {
+ wl_radiotap_vht_t *rtvht = (wl_radiotap_vht_t *)skb->data;
+
+ rtvht->ieee_radiotap.it_version = 0;
+ rtvht->ieee_radiotap.it_pad = 0;
+ rtvht->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtvht->ieee_radiotap.it_present =
+ HTOL32(WL_RADIOTAP_PRESENT_VHT);
+
+ rtvht->tsft_l = htol32(rxsts->mactime);
+ rtvht->tsft_h = 0;
+ rtvht->flags = flags;
+ rtvht->pad1 = 0;
+ rtvht->channel_freq = HTOL16(channel_frequency);
+ rtvht->channel_flags = HTOL16(channel_flags);
+ rtvht->signal = (int8)rxsts->signal;
+ rtvht->noise = (int8)rxsts->noise;
+ rtvht->antenna = rxsts->antenna;
+
+ rtvht->vht_known = (IEEE80211_RADIOTAP_VHT_HAVE_STBC |
+ IEEE80211_RADIOTAP_VHT_HAVE_TXOP_PS |
+ IEEE80211_RADIOTAP_VHT_HAVE_GI |
+ IEEE80211_RADIOTAP_VHT_HAVE_SGI_NSYM_DA |
+ IEEE80211_RADIOTAP_VHT_HAVE_LDPC_EXTRA |
+ IEEE80211_RADIOTAP_VHT_HAVE_BF |
+ IEEE80211_RADIOTAP_VHT_HAVE_BW |
+ IEEE80211_RADIOTAP_VHT_HAVE_GID |
+ IEEE80211_RADIOTAP_VHT_HAVE_PAID);
+
+ STATIC_ASSERT(WL_RXS_VHTF_STBC ==
+ IEEE80211_RADIOTAP_VHT_STBC);
+ STATIC_ASSERT(WL_RXS_VHTF_TXOP_PS ==
+ IEEE80211_RADIOTAP_VHT_TXOP_PS);
+ STATIC_ASSERT(WL_RXS_VHTF_SGI ==
+ IEEE80211_RADIOTAP_VHT_SGI);
+ STATIC_ASSERT(WL_RXS_VHTF_SGI_NSYM_DA ==
+ IEEE80211_RADIOTAP_VHT_SGI_NSYM_DA);
+ STATIC_ASSERT(WL_RXS_VHTF_LDPC_EXTRA ==
+ IEEE80211_RADIOTAP_VHT_LDPC_EXTRA);
+ STATIC_ASSERT(WL_RXS_VHTF_BF ==
+ IEEE80211_RADIOTAP_VHT_BF);
+
+ rtvht->vht_flags = HTOL16(rxsts->vhtflags);
+
+ STATIC_ASSERT(WL_RXS_VHT_BW_20 ==
+ IEEE80211_RADIOTAP_VHT_BW_20);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40 ==
+ IEEE80211_RADIOTAP_VHT_BW_40);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20L ==
+ IEEE80211_RADIOTAP_VHT_BW_20L);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20U ==
+ IEEE80211_RADIOTAP_VHT_BW_20U);
+ STATIC_ASSERT(WL_RXS_VHT_BW_80 ==
+ IEEE80211_RADIOTAP_VHT_BW_80);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40L ==
+ IEEE80211_RADIOTAP_VHT_BW_40L);
+ STATIC_ASSERT(WL_RXS_VHT_BW_40U ==
+ IEEE80211_RADIOTAP_VHT_BW_40U);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20LL ==
+ IEEE80211_RADIOTAP_VHT_BW_20LL);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20LU ==
+ IEEE80211_RADIOTAP_VHT_BW_20LU);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20UL ==
+ IEEE80211_RADIOTAP_VHT_BW_20UL);
+ STATIC_ASSERT(WL_RXS_VHT_BW_20UU ==
+ IEEE80211_RADIOTAP_VHT_BW_20UU);
+
+ rtvht->vht_bw = rxsts->bw;
+
+ rtvht->vht_mcs_nss[0] = (rxsts->mcs << 4) |
+ (rxsts->nss & IEEE80211_RADIOTAP_VHT_NSS);
+ rtvht->vht_mcs_nss[1] = 0;
+ rtvht->vht_mcs_nss[2] = 0;
+ rtvht->vht_mcs_nss[3] = 0;
+
+ STATIC_ASSERT(WL_RXS_VHTF_CODING_LDCP ==
+ IEEE80211_RADIOTAP_VHT_CODING_LDPC);
+
+ rtvht->vht_coding = rxsts->coding;
+ rtvht->vht_group_id = rxsts->gid;
+ rtvht->vht_partial_aid = HTOL16(rxsts->aid);
+
+ rtvht->ampdu_flags = 0;
+ rtvht->ampdu_delim_crc = 0;
+
+ rtvht->ampdu_ref_num = rxsts->ampdu_counter;
+
+ if (!(rxsts->nfrmtype & WL_RXS_NFRM_AMPDU_FIRST) &&
+ !(rxsts->nfrmtype & WL_RXS_NFRM_AMPDU_SUB))
+ rtvht->ampdu_flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
+
+ if (rxsts->nfrmtype & WL_RXS_NFRM_AMPDU_NONE)
+ rtvht->ampdu_flags |= IEEE80211_RADIOTAP_AMPDU_MPDU_ONLY;
+ }
+ else if (rxsts->encoding == WL_RXS_ENCODING_HT) {
+ wl_radiotap_ht_t *rtht =
+ (wl_radiotap_ht_t *)skb->data;
+
+ rtht->ieee_radiotap.it_version = 0;
+ rtht->ieee_radiotap.it_pad = 0;
+ rtht->ieee_radiotap.it_len = HTOL16(rtap_len);
+ rtht->ieee_radiotap.it_present
+ = HTOL32(WL_RADIOTAP_PRESENT_HT);
+ rtht->pad1 = 0;
+
+ rtht->tsft_l = htol32(rxsts->mactime);
+ rtht->tsft_h = 0;
+ rtht->flags = flags;
+ rtht->channel_freq = HTOL16(channel_frequency);
+ rtht->channel_flags = HTOL16(channel_flags);
+ rtht->signal = (int8)rxsts->signal;
+ rtht->noise = (int8)rxsts->noise;
+ rtht->antenna = rxsts->antenna;
+
+ rtht->mcs_known = (IEEE80211_RADIOTAP_MCS_HAVE_BW |
+ IEEE80211_RADIOTAP_MCS_HAVE_MCS |
+ IEEE80211_RADIOTAP_MCS_HAVE_GI |
+ IEEE80211_RADIOTAP_MCS_HAVE_FEC |
+ IEEE80211_RADIOTAP_MCS_HAVE_FMT);
+
+ rtht->mcs_flags = 0;
+ switch (rxsts->htflags & WL_RXS_HTF_BW_MASK) {
+ case WL_RXS_HTF_20L:
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20L;
+ break;
+ case WL_RXS_HTF_20U:
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20U;
+ break;
+ case WL_RXS_HTF_40:
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_40;
+ break;
+ default:
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20;
+ }
+
+ if (rxsts->htflags & WL_RXS_HTF_SGI) {
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_SGI;
+ }
+ if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF) {
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_FMT_GF;
+ }
+ if (rxsts->htflags & WL_RXS_HTF_LDPC) {
+ rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_FEC_LDPC;
+ }
+ rtht->mcs_index = rxsts->mcs;
+ }
+
+ pdata = skb->data + rtap_len;
+ bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
+
+ if (oskb->next) {
+ struct sk_buff *amsdu_p = oskb->next;
+ amsdu_p = oskb->next;
+ pdata += (oskb->len - D11_PHY_HDR_LEN);
+ while (amsdu_p) {
+ bcopy(amsdu_p->data, pdata, amsdu_p->len);
+ pdata += amsdu_p->len;
+ amsdu_p = amsdu_p->next;
+ }
+ }
+ }
+
+ if (skb == NULL) return;
+
+ skb->dev = wl->monitor_dev;
+ skb->dev->last_rx = jiffies;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+ skb_reset_mac_header(skb);
+#else
+ skb->mac.raw = skb->data;
+#endif
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_80211_RAW);
+
+ netif_rx(skb);
+}
+
+static int
+wl_monitor_start(struct sk_buff *skb, struct net_device *dev)
+{
+ wl_info_t *wl;
+
+ wl = WL_DEV_IF(dev)->wl;
+ PKTFREE(wl->osh, skb, FALSE);
+ return 0;
+}
+
+static void
+_wl_add_monitor_if(wl_task_t *task)
+{
+ struct net_device *dev;
+ wl_if_t *wlif = (wl_if_t *) task->context;
+ wl_info_t *wl = wlif->wl;
+
+ WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__));
+ ASSERT(wl);
+ ASSERT(!wl->monitor_dev);
+
+ if ((dev = wl_alloc_linux_if(wlif)) == NULL) {
+ WL_ERROR(("wl%d: %s: wl_alloc_linux_if failed\n", wl->pub->unit, __FUNCTION__));
+ goto done;
+ }
+
+ ASSERT(strlen(wlif->name) > 0);
+ strncpy(wlif->dev->name, wlif->name, strlen(wlif->name));
+
+ wl->monitor_dev = dev;
+ if (wl->monitor_type == 1)
+ dev->type = ARPHRD_IEEE80211_PRISM;
+ else
+ dev->type = ARPHRD_IEEE80211_RADIOTAP;
+
+ bcopy(wl->dev->dev_addr, dev->dev_addr, ETHER_ADDR_LEN);
+
+#if defined(WL_USE_NETDEV_OPS)
+ dev->netdev_ops = &wl_netdev_monitor_ops;
+#else
+ dev->hard_start_xmit = wl_monitor_start;
+ dev->do_ioctl = wl_ioctl;
+ dev->get_stats = wl_get_stats;
+#endif
+
+ if (register_netdev(dev)) {
+ WL_ERROR(("wl%d: %s, register_netdev failed for %s\n",
+ wl->pub->unit, __FUNCTION__, wl->monitor_dev->name));
+ wl->monitor_dev = NULL;
+ goto done;
+ }
+ wlif->dev_registed = TRUE;
+
+done:
+ MFREE(wl->osh, task, sizeof(wl_task_t));
+ atomic_dec(&wl->callbacks);
+}
+
+static void
+_wl_del_monitor(wl_task_t *task)
+{
+ wl_info_t *wl = (wl_info_t *) task->context;
+
+ ASSERT(wl);
+ ASSERT(wl->monitor_dev);
+
+ WL_TRACE(("wl%d: _wl_del_monitor\n", wl->pub->unit));
+
+ wl_free_if(wl, WL_DEV_IF(wl->monitor_dev));
+ wl->monitor_dev = NULL;
+
+ MFREE(wl->osh, task, sizeof(wl_task_t));
+ atomic_dec(&wl->callbacks);
+}
+
+void
+wl_set_monitor(wl_info_t *wl, int val)
+{
+ const char *devname;
+ wl_if_t *wlif;
+
+ WL_TRACE(("wl%d: wl_set_monitor: val %d\n", wl->pub->unit, val));
+ if ((val && wl->monitor_dev) || (!val && !wl->monitor_dev)) {
+ WL_ERROR(("%s: Mismatched params, return\n", __FUNCTION__));
+ return;
+ }
+
+ if (!val) {
+ (void) wl_schedule_task(wl, _wl_del_monitor, wl);
+ return;
+ }
+
+ if (val >= 1 && val <= 3) {
+ wl->monitor_type = val;
+ } else {
+ WL_ERROR(("monitor type %d not supported\n", val));
+ ASSERT(0);
+ }
+
+ wlif = wl_alloc_if(wl, WL_IFTYPE_MON, wl->pub->unit, NULL);
+ if (!wlif) {
+ WL_ERROR(("wl%d: %s: alloc wlif failed\n", wl->pub->unit, __FUNCTION__));
+ return;
+ }
+
+ if (wl->monitor_type == 1)
+ devname = "prism";
+ else
+ devname = "radiotap";
+ sprintf(wlif->name, "%s%d", devname, wl->pub->unit);
+
+ if (wl_schedule_task(wl, _wl_add_monitor_if, wlif)) {
+ MFREE(wl->osh, wlif, sizeof(wl_if_t));
+ return;
+ }
+}
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
+const char *
+print_tainted()
+{
+ return "";
+}
+#endif
+
+struct net_device *
+wl_netdev_get(wl_info_t *wl)
+{
+ return wl->dev;
+}
+
+int
+wl_set_pktlen(osl_t *osh, void *p, int len)
+{
+ PKTSETLEN(osh, p, len);
+ return len;
+}
+
+void *
+wl_get_pktbuffer(osl_t *osh, int len)
+{
+ return (PKTGET(osh, len, FALSE));
+}
+
+uint
+wl_buf_to_pktcopy(osl_t *osh, void *p, uchar *buf, int len, uint offset)
+{
+ if (PKTLEN(osh, p) < len + offset)
+ return 0;
+ bcopy(buf, (char *)PKTDATA(osh, p) + offset, len);
+ return len;
+}
+
+#if defined(WL_CONFIG_RFKILL)
+
+static int
+wl_set_radio_block(void *data, bool blocked)
+{
+ wl_info_t *wl = data;
+ uint32 radioval;
+
+ WL_TRACE(("%s: kernel set blocked = %d\n", __FUNCTION__, blocked));
+
+ radioval = WL_RADIO_SW_DISABLE << 16 | blocked;
+
+ WL_LOCK(wl);
+
+ if (wlc_set(wl->wlc, WLC_SET_RADIO, radioval) < 0) {
+ WL_ERROR(("%s: SET_RADIO failed\n", __FUNCTION__));
+ return 1;
+ }
+
+ WL_UNLOCK(wl);
+
+ return 0;
+}
+
+static const struct rfkill_ops bcmwl_rfkill_ops = {
+ .set_block = wl_set_radio_block
+};
+
+static int
+wl_init_rfkill(wl_info_t *wl)
+{
+ int status;
+
+ snprintf(wl->wl_rfkill.rfkill_name, sizeof(wl->wl_rfkill.rfkill_name),
+ "brcmwl-%d", wl->pub->unit);
+
+ wl->wl_rfkill.rfkill = rfkill_alloc(wl->wl_rfkill.rfkill_name, &wl->dev->dev,
+ RFKILL_TYPE_WLAN, &bcmwl_rfkill_ops, wl);
+
+ if (!wl->wl_rfkill.rfkill) {
+ WL_ERROR(("%s: RFKILL: Failed to allocate rfkill\n", __FUNCTION__));
+ return -ENOMEM;
+ }
+
+ if (wlc_get(wl->wlc, WLC_GET_RADIO, &status) < 0) {
+ WL_ERROR(("%s: WLC_GET_RADIO failed\n", __FUNCTION__));
+ return 1;
+ }
+
+ rfkill_init_sw_state(wl->wl_rfkill.rfkill, status);
+
+ if (rfkill_register(wl->wl_rfkill.rfkill)) {
+ WL_ERROR(("%s: rfkill_register failed! \n", __FUNCTION__));
+ rfkill_destroy(wl->wl_rfkill.rfkill);
+ return 2;
+ }
+
+ WL_ERROR(("%s: rfkill registered\n", __FUNCTION__));
+ wl->wl_rfkill.registered = TRUE;
+ return 0;
+}
+
+static void
+wl_uninit_rfkill(wl_info_t *wl)
+{
+ if (wl->wl_rfkill.registered) {
+ rfkill_unregister(wl->wl_rfkill.rfkill);
+ rfkill_destroy(wl->wl_rfkill.rfkill);
+ wl->wl_rfkill.registered = FALSE;
+ wl->wl_rfkill.rfkill = NULL;
+ }
+}
+
+static void
+wl_report_radio_state(wl_info_t *wl)
+{
+ WL_TRACE(("%s: report radio state %d\n", __FUNCTION__, wl->last_phyind));
+
+ rfkill_set_hw_state(wl->wl_rfkill.rfkill, wl->last_phyind != 0);
+}
+
+#endif
+
+static int
+wl_linux_watchdog(void *ctx)
+{
+ wl_info_t *wl = (wl_info_t *) ctx;
+ struct net_device_stats *stats = NULL;
+ uint id;
+ wl_if_t *wlif;
+ wlc_if_stats_t wlcif_stats;
+#ifdef USE_IW
+ struct iw_statistics *wstats = NULL;
+ int phy_noise;
+#endif
+ if (wl == NULL)
+ return -1;
+
+ if (wl->if_list) {
+ for (wlif = wl->if_list; wlif != NULL; wlif = wlif->next) {
+ memset(&wlcif_stats, 0, sizeof(wlc_if_stats_t));
+ wlc_wlcif_stats_get(wl->wlc, wlif->wlcif, &wlcif_stats);
+
+ if (wl->pub->up) {
+ ASSERT(wlif->stats_id < 2);
+
+ id = 1 - wlif->stats_id;
+ stats = &wlif->stats_watchdog[id];
+ if (stats) {
+ stats->rx_packets = WLCNTVAL(wlcif_stats.rxframe);
+ stats->tx_packets = WLCNTVAL(wlcif_stats.txframe);
+ stats->rx_bytes = WLCNTVAL(wlcif_stats.rxbyte);
+ stats->tx_bytes = WLCNTVAL(wlcif_stats.txbyte);
+ stats->rx_errors = WLCNTVAL(wlcif_stats.rxerror);
+ stats->tx_errors = WLCNTVAL(wlcif_stats.txerror);
+ stats->collisions = 0;
+ stats->rx_length_errors = 0;
+
+ stats->rx_over_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
+ stats->rx_crc_errors = WLCNTVAL(wl->pub->_cnt->rxcrc);
+ stats->rx_frame_errors = 0;
+ stats->rx_fifo_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
+ stats->rx_missed_errors = 0;
+ stats->tx_fifo_errors = 0;
+ }
+
+#ifdef USE_IW
+ wstats = &wlif->wstats_watchdog[id];
+ if (wstats) {
+#if WIRELESS_EXT > 11
+ wstats->discard.nwid = 0;
+ wstats->discard.code = WLCNTVAL(wl->pub->_cnt->rxundec);
+ wstats->discard.fragment = WLCNTVAL(wlcif_stats.rxfragerr);
+ wstats->discard.retries = WLCNTVAL(wlcif_stats.txfail);
+ wstats->discard.misc = WLCNTVAL(wl->pub->_cnt->rxrunt) +
+ WLCNTVAL(wl->pub->_cnt->rxgiant);
+ wstats->miss.beacon = 0;
+#endif
+ }
+#endif
+
+ wlif->stats_id = id;
+ }
+#ifdef USE_IW
+ if (!wlc_get(wl->wlc, WLC_GET_PHY_NOISE, &phy_noise))
+ wlif->phy_noise = phy_noise;
+#endif
+
+ }
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+static int
+wl_proc_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ wl_info_t * wl = (wl_info_t *)data;
+#else
+static ssize_t
+wl_proc_read(struct file *filp, char __user *buffer, size_t length, loff_t *offp)
+{
+ wl_info_t * wl = PDE_DATA(file_inode(filp));
+#endif
+ int bcmerror, len;
+ int to_user = 0;
+ char tmp[8];
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+ if (offset > 0) {
+ *eof = 1;
+ return 0;
+ }
+#else
+ if (*offp > 0) {
+ return 0;
+ }
+#endif
+
+ WL_LOCK(wl);
+ bcmerror = wlc_ioctl(wl->wlc, WLC_GET_MONITOR, &to_user, sizeof(int), NULL);
+ WL_UNLOCK(wl);
+
+ if (bcmerror != BCME_OK) {
+ WL_ERROR(("%s: GET_MONITOR failed with %d\n", __FUNCTION__, bcmerror));
+ return -EIO;
+ }
+
+ len = snprintf(tmp, ARRAY_SIZE(tmp), "%d\n", to_user);
+ tmp[ARRAY_SIZE(tmp) - 1] = '\0';
+ if ((len < 0) || (len >= ARRAY_SIZE(tmp))) {
+ WL_ERROR(("%s: tmp array not big enough %d > %zu", __FUNCTION__, len, ARRAY_SIZE(tmp)));
+ return -ERANGE;
+ }
+ if (length < len) {
+ WL_ERROR(( "%s: user buffer is too small (%d < %d)", __FUNCTION__, (int)length, len));
+ return -EMSGSIZE;
+ }
+ if (copy_to_user(buffer, tmp, len) != 0) {
+ WL_ERROR(( "%s: unable to copy data!", __FUNCTION__));
+ return -EFAULT;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+ *offp += len;
+#endif
+
+ return len;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+static int
+wl_proc_write(struct file *filp, const char *buff, unsigned long length, void *data)
+{
+ wl_info_t * wl = (wl_info_t *)data;
+#else
+static ssize_t
+wl_proc_write(struct file *filp, const char __user *buff, size_t length, loff_t *offp)
+{
+ wl_info_t * wl = PDE_DATA(file_inode(filp));
+#endif
+ int from_user = 0;
+ int bcmerror;
+
+ if (length == 0 || length > 2) {
+
+ WL_ERROR(("%s: Invalid data length\n", __FUNCTION__));
+ return -EIO;
+ }
+ if (copy_from_user(&from_user, buff, 1)) {
+ WL_ERROR(("%s: copy from user failed\n", __FUNCTION__));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+ return -EIO;
+#else
+ return -EFAULT;
+#endif
+ }
+
+ if (from_user >= 0x30)
+ from_user -= 0x30;
+
+ WL_LOCK(wl);
+ bcmerror = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &from_user, sizeof(int), NULL);
+ WL_UNLOCK(wl);
+
+ if (bcmerror != BCME_OK) {
+ WL_ERROR(("%s: SET_MONITOR failed with %d\n", __FUNCTION__, bcmerror));
+ return -EIO;
+ }
+ return length;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
+static const struct file_operations wl_fops = {
+ .owner = THIS_MODULE,
+ .read = wl_proc_read,
+ .write = wl_proc_write,
+};
+#endif
+
+static int
+wl_reg_proc_entry(wl_info_t *wl)
+{
+ char tmp[32];
+ sprintf(tmp, "%s%d", HYBRID_PROC, wl->pub->unit);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+ if ((wl->proc_entry = create_proc_entry(tmp, 0644, NULL)) == NULL) {
+ WL_ERROR(("%s: create_proc_entry %s failed\n", __FUNCTION__, tmp));
+#else
+ if ((wl->proc_entry = proc_create_data(tmp, 0644, NULL, &wl_fops, wl)) == NULL) {
+ WL_ERROR(("%s: proc_create_data %s failed\n", __FUNCTION__, tmp));
+#endif
+ ASSERT(0);
+ return -1;
+ }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+ wl->proc_entry->read_proc = wl_proc_read;
+ wl->proc_entry->write_proc = wl_proc_write;
+ wl->proc_entry->data = wl;
+#endif
+ return 0;
+}
+uint32 wl_pcie_bar1(struct wl_info *wl, uchar** addr)
+{
+ *addr = wl->bar1_addr;
+ return (wl->bar1_size);
+}
diff --git a/src/wl/sys/wl_linux.h b/src/wl/sys/wl_linux.h
new file mode 100644
index 0000000..5b1048e
--- /dev/null
+++ b/src/wl/sys/wl_linux.h
@@ -0,0 +1,192 @@
+/*
+ * wl_linux.c exported functions and definitions
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wl_linux.h 369548 2012-11-19 09:01:01Z $
+ */
+
+#ifndef _wl_linux_h_
+#define _wl_linux_h_
+
+#include <wlc_types.h>
+
+typedef struct wl_timer {
+ struct timer_list timer;
+ struct wl_info *wl;
+ void (*fn)(void *);
+ void *arg;
+ uint ms;
+ bool periodic;
+ bool set;
+ struct wl_timer *next;
+#ifdef BCMDBG
+ char* name;
+ uint32 ticks;
+#endif
+} wl_timer_t;
+
+typedef struct wl_task {
+ struct work_struct work;
+ void *context;
+} wl_task_t;
+
+#define WL_IFTYPE_BSS 1
+#define WL_IFTYPE_WDS 2
+#define WL_IFTYPE_MON 3
+
+struct wl_if {
+#ifdef USE_IW
+ wl_iw_t iw;
+#endif
+ struct wl_if *next;
+ struct wl_info *wl;
+ struct net_device *dev;
+ struct wlc_if *wlcif;
+ uint subunit;
+ bool dev_registed;
+ int if_type;
+ char name[IFNAMSIZ];
+ struct net_device_stats stats;
+ uint stats_id;
+ struct net_device_stats stats_watchdog[2];
+
+#ifdef USE_IW
+ struct iw_statistics wstats_watchdog[2];
+ struct iw_statistics wstats;
+ int phy_noise;
+#endif
+};
+
+struct rfkill_stuff {
+ struct rfkill *rfkill;
+ char rfkill_name[32];
+ char registered;
+};
+
+struct wl_info {
+ uint unit;
+ wlc_pub_t *pub;
+ void *wlc;
+ osl_t *osh;
+ struct net_device *dev;
+
+ struct semaphore sem;
+ spinlock_t lock;
+ spinlock_t isr_lock;
+
+ uint bcm_bustype;
+ bool piomode;
+ void *regsva;
+ wl_if_t *if_list;
+ atomic_t callbacks;
+ struct wl_timer *timers;
+ struct tasklet_struct tasklet;
+ struct tasklet_struct tx_tasklet;
+
+#if 0 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+ struct napi_struct napi;
+#endif
+
+ struct net_device *monitor_dev;
+ uint monitor_type;
+ bool resched;
+ uint32 pci_psstate[16];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
+#define NUM_GROUP_KEYS 4
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+ struct lib80211_crypto_ops *tkipmodops;
+#else
+ struct ieee80211_crypto_ops *tkipmodops;
+#endif
+ struct ieee80211_tkip_data *tkip_ucast_data;
+ struct ieee80211_tkip_data *tkip_bcast_data[NUM_GROUP_KEYS];
+#endif
+
+ bool txq_dispatched;
+ spinlock_t txq_lock;
+ struct sk_buff *txq_head;
+ struct sk_buff *txq_tail;
+ int txq_cnt;
+
+ wl_task_t txq_task;
+ wl_task_t multicast_task;
+
+ wl_task_t wl_dpc_task;
+ bool all_dispatch_mode;
+
+#if defined(WL_CONFIG_RFKILL)
+ struct rfkill_stuff wl_rfkill;
+ mbool last_phyind;
+#endif
+
+ uint processed;
+ struct proc_dir_entry *proc_entry;
+ uchar* bar1_addr;
+ uint32 bar1_size;
+};
+
+#define HYBRID_PROC "brcm_monitor"
+
+#if defined(WL_ALL_PASSIVE_ON)
+#define WL_ALL_PASSIVE_ENAB(wl) 1
+#else
+#define WL_ALL_PASSIVE_ENAB(wl) (!(wl)->all_dispatch_mode)
+#endif
+
+#define WL_LOCK(wl) \
+do { \
+ if (WL_ALL_PASSIVE_ENAB(wl)) \
+ down(&(wl)->sem); \
+ else \
+ spin_lock_bh(&(wl)->lock); \
+} while (0)
+
+#define WL_UNLOCK(wl) \
+do { \
+ if (WL_ALL_PASSIVE_ENAB(wl)) \
+ up(&(wl)->sem); \
+ else \
+ spin_unlock_bh(&(wl)->lock); \
+} while (0)
+
+#define WL_ISRLOCK(wl, flags) do {spin_lock(&(wl)->isr_lock); (void)(flags);} while (0)
+#define WL_ISRUNLOCK(wl, flags) do {spin_unlock(&(wl)->isr_lock); (void)(flags);} while (0)
+
+#define INT_LOCK(wl, flags) spin_lock_irqsave(&(wl)->isr_lock, flags)
+#define INT_UNLOCK(wl, flags) spin_unlock_irqrestore(&(wl)->isr_lock, flags)
+
+typedef struct wl_info wl_info_t;
+
+#ifndef PCI_D0
+#define PCI_D0 0
+#endif
+
+#ifndef PCI_D3hot
+#define PCI_D3hot 3
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+extern irqreturn_t wl_isr(int irq, void *dev_id);
+#else
+extern irqreturn_t wl_isr(int irq, void *dev_id, struct pt_regs *ptregs);
+#endif
+
+extern int __devinit wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+extern void wl_free(wl_info_t *wl);
+extern int wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+extern struct net_device * wl_netdev_get(wl_info_t *wl);
+
+#endif
diff --git a/src/wl/sys/wlc_ethereal.h b/src/wl/sys/wlc_ethereal.h
new file mode 100644
index 0000000..2f9e128
--- /dev/null
+++ b/src/wl/sys/wlc_ethereal.h
@@ -0,0 +1,129 @@
+/*
+ * Structures and defines for the prism-style rx header that Ethereal
+ * understands.
+ * Broadcom 802.11abg Networking Device Driver
+ * Derived from http://airsnort.shmoo.com/orinoco-09b-packet-1.diff
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_ethereal.h 328348 2012-04-18 22:57:38Z $
+ */
+
+#ifndef _WLC_ETHEREAL_H_
+#define _WLC_ETHEREAL_H_
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+#ifndef ARPHRD_ETHER
+#define ARPHRD_ETHER 1
+#endif
+
+#ifndef ARPHRD_IEEE80211_PRISM
+#define ARPHRD_IEEE80211_PRISM 802
+#endif
+
+#define DNAMELEN 16
+
+#define WL_MON_FRAME 0x0041
+#define WL_MON_FRAME_HOSTTIME 0x1041
+#define WL_MON_FRAME_MACTIME 0x2041
+#define WL_MON_FRAME_CHANNEL 0x3041
+#define WL_MON_FRAME_RSSI 0x4041
+#define WL_MON_FRAME_SQ 0x5041
+#define WL_MON_FRAME_SIGNAL 0x6041
+#define WL_MON_FRAME_NOISE 0x7041
+#define WL_MON_FRAME_RATE 0x8041
+#define WL_MON_FRAME_ISTX 0x9041
+#define WL_MON_FRAME_FRMLEN 0xA041
+
+#define P80211ITEM_OK 0
+#define P80211ITEM_NO_VALUE 1
+
+typedef struct p80211item
+{
+ uint32 did;
+ uint16 status;
+ uint16 len;
+ uint32 data;
+} p80211item_t;
+
+typedef struct p80211msg
+{
+ uint32 msgcode;
+ uint32 msglen;
+ uint8 devname[DNAMELEN];
+ p80211item_t hosttime;
+ p80211item_t mactime;
+ p80211item_t channel;
+ p80211item_t rssi;
+ p80211item_t sq;
+ p80211item_t signal;
+ p80211item_t noise;
+ p80211item_t rate;
+ p80211item_t istx;
+ p80211item_t frmlen;
+} p80211msg_t;
+
+#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
+
+#define WLANCAP_PHY_UNKOWN 0
+#define WLANCAP_PHY_FHSS_97 1
+#define WLANCAP_PHY_DSSS_97 2
+#define WLANCAP_PHY_IR 3
+#define WLANCAP_PHY_DSSS_11B 4
+#define WLANCAP_PHY_PBCC_11B 5
+#define WLANCAP_PHY_OFDM_11G 6
+#define WLANCAP_PHY_PBCC_11G 7
+#define WLANCAP_PHY_OFDM_11A 8
+#define WLANCAP_PHY_OFDM_11N 9
+
+#define WLANCAP_ENCODING_UNKNOWN 0
+#define WLANCAP_ENCODING_CCK 1
+#define WLANCAP_ENCODING_PBCC 2
+#define WLANCAP_ENCODING_OFDM 3
+
+#define WLANCAP_SSI_TYPE_NONE 0
+#define WLANCAP_SSI_TYPE_NORM 1
+#define WLANCAP_SSI_TYPE_DBM 2
+#define WLANCAP_SSI_TYPE_RAW 3
+
+#define WLANCAP_PREAMBLE_UNKNOWN 0
+#define WLANCAP_PREAMBLE_SHORT 1
+#define WLANCAP_PREAMBLE_LONG 2
+#define WLANCAP_PREAMBLE_MIMO_MM 3
+#define WLANCAP_PREAMBLE_MIMO_GF 4
+
+typedef struct wlan_header_v1 {
+ uint32 version;
+ uint32 length;
+ uint32 mactime_h;
+ uint32 mactime_l;
+ uint32 hosttime_h;
+ uint32 hosttime_l;
+ uint32 phytype;
+ uint32 channel;
+ uint32 datarate;
+ uint32 antenna;
+ uint32 priority;
+ uint32 ssi_type;
+ int32 ssi_signal;
+ int32 ssi_noise;
+ uint32 preamble;
+ uint32 encoding;
+} wlan_header_v1_t;
+
+#endif
diff --git a/src/wl/sys/wlc_key.h b/src/wl/sys/wlc_key.h
new file mode 100644
index 0000000..dfe99df
--- /dev/null
+++ b/src/wl/sys/wlc_key.h
@@ -0,0 +1,76 @@
+/*
+ * Key management related declarations
+ * and exported functions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_key.h 458427 2014-02-26 23:12:38Z $
+ */
+
+#ifndef _wlc_key_h_
+#define _wlc_key_h_
+
+#include <bcmcrypto/tkhash.h>
+
+typedef struct tkip_info {
+ uint16 phase1[TKHASH_P1_KEY_SIZE/sizeof(uint16)];
+ uint8 phase2[TKHASH_P2_KEY_SIZE];
+ uint32 micl;
+ uint32 micr;
+} tkip_info_t;
+
+typedef struct wsec_iv {
+ uint32 hi;
+ uint16 lo;
+} wsec_iv_t;
+
+#define WLC_NUMRXIVS 4
+
+#define TWSIZE 128
+
+typedef struct wsec_key {
+ struct ether_addr ea;
+ uint8 idx;
+ uint8 id;
+ uint8 algo;
+ uint8 rcmta;
+ uint16 flags;
+ uint8 algo_hw;
+ uint8 aes_mode;
+ int8 iv_len;
+ int8 icv_len;
+ uint32 len;
+
+ uint8 data[DOT11_MAX_KEY_SIZE];
+ wsec_iv_t rxiv[WLC_NUMRXIVS];
+ wsec_iv_t txiv;
+ tkip_info_t tkip_tx;
+ tkip_info_t tkip_rx;
+ uint32 tkip_rx_iv32;
+ uint8 tkip_rx_ividx;
+ uint8 tkip_tx_lefts;
+ uint8 tkip_tx_left[4];
+ uint16 tkip_tx_offset;
+ uint8 tkip_tx_fmic[8];
+ int tkip_tx_fmic_written;
+
+#if defined(UCODE_SEQ)
+ wsec_iv_t bk_iv;
+ tkip_info_t tkip_bk_tx;
+#endif
+} wsec_key_t;
+
+#endif
diff --git a/src/wl/sys/wlc_pub.h b/src/wl/sys/wlc_pub.h
new file mode 100644
index 0000000..53a98b8
--- /dev/null
+++ b/src/wl/sys/wlc_pub.h
@@ -0,0 +1,927 @@
+/*
+ * Common (OS-independent) definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_pub.h 458427 2014-02-26 23:12:38Z $
+ */
+
+#ifndef _wlc_pub_h_
+#define _wlc_pub_h_
+
+#include <wlc_types.h>
+#include <wlc_utils.h>
+#include "proto/802.11.h"
+#include "proto/bcmevent.h"
+
+#define MAX_TIMERS (34 + WLC_MAXMFPS + WLC_MAXDLS_TIMERS + (2 * WLC_MAXDPT))
+
+#define WLC_NUMRATES 16
+#define MAXMULTILIST 32
+#define D11_PHY_HDR_LEN 6
+
+#define PHY_TYPE_A 0
+#define PHY_TYPE_G 2
+#define PHY_TYPE_N 4
+#define PHY_TYPE_LP 5
+#define PHY_TYPE_SSN 6
+#define PHY_TYPE_HT 7
+#define PHY_TYPE_LCN 8
+#define PHY_TYPE_LCNXN 9
+
+#define WLC_10_MHZ 10
+#define WLC_20_MHZ 20
+#define WLC_40_MHZ 40
+#define WLC_80_MHZ 80
+#define WLC_160_MHZ 160
+
+#define CHSPEC_WLC_BW(chanspec)(CHSPEC_IS160(chanspec) ? WLC_160_MHZ : \
+ CHSPEC_IS80(chanspec) ? WLC_80_MHZ : \
+ CHSPEC_IS40(chanspec) ? WLC_40_MHZ : \
+ CHSPEC_IS20(chanspec) ? WLC_20_MHZ : \
+ WLC_10_MHZ)
+
+#define WLC_RSSI_MINVAL -200
+#define WLC_RSSI_NO_SIGNAL -91
+#define WLC_RSSI_VERY_LOW -80
+#define WLC_RSSI_LOW -70
+#define WLC_RSSI_GOOD -68
+#define WLC_RSSI_VERY_GOOD -58
+#define WLC_RSSI_EXCELLENT -57
+
+#define PREFSZ 160
+#define WLPREFHDRS(h, sz) OSL_PREF_RANGE_ST((h), (sz))
+
+struct wlc_info;
+struct wlc_hw_info;
+struct wlc_bsscfg;
+struct wlc_if;
+
+typedef struct wlc_tunables {
+ int ntxd;
+ int nrxd;
+ int rxbufsz;
+ int nrxbufpost;
+ int maxscb;
+ int ampdunummpdu2streams;
+ int ampdunummpdu3streams;
+ int maxpktcb;
+ int maxdpt;
+ int maxucodebss;
+ int maxucodebss4;
+ int maxbss;
+ int datahiwat;
+ int ampdudatahiwat;
+ int rxbnd;
+ int txsbnd;
+ int pktcbnd;
+ int dngl_mem_restrict_rxdma;
+ int rpctxbufpost;
+ int pkt_maxsegs;
+ int maxscbcubbies;
+ int maxbsscfgcubbies;
+ int max_notif_servers;
+ int max_notif_clients;
+ int max_mempools;
+ int maxtdls;
+ int amsdu_resize_buflen;
+ int ampdu_pktq_size;
+ int ampdu_pktq_fav_size;
+ int ntxd_large;
+ int nrxd_large;
+ int wlfcfifocreditac0;
+ int wlfcfifocreditac1;
+ int wlfcfifocreditac2;
+ int wlfcfifocreditac3;
+ int wlfcfifocreditbcmc;
+ int wlfcfifocreditother;
+ int scan_settle_time;
+ int wlfc_fifo_cr_pending_thresh_ac_bk;
+ int wlfc_fifo_cr_pending_thresh_ac_be;
+ int wlfc_fifo_cr_pending_thresh_ac_vi;
+ int wlfc_fifo_cr_pending_thresh_ac_vo;
+ int ampdunummpdu1stream;
+} wlc_tunables_t;
+
+typedef struct wlc_rateset {
+ uint count;
+ uint8 rates[WLC_NUMRATES];
+ uint8 htphy_membership;
+ uint8 mcs[MCSSET_LEN];
+ uint16 vht_mcsmap;
+} wlc_rateset_t;
+
+typedef void *wlc_pkt_t;
+
+typedef struct wlc_event {
+ wl_event_msg_t event;
+ struct ether_addr *addr;
+ struct wlc_if *wlcif;
+ void *data;
+ struct wlc_event *next;
+} wlc_event_t;
+
+typedef struct wlc_bss_info
+{
+ struct ether_addr BSSID;
+ uint16 flags;
+ uint8 SSID_len;
+ uint8 SSID[32];
+ int16 RSSI;
+ int16 SNR;
+ uint16 beacon_period;
+ uint16 atim_window;
+ chanspec_t chanspec;
+ int8 infra;
+ wlc_rateset_t rateset;
+ uint8 dtim_period;
+ int8 phy_noise;
+ uint16 capability;
+ struct dot11_bcn_prb *bcn_prb;
+ uint16 bcn_prb_len;
+ uint8 wme_qosinfo;
+ struct rsn_parms wpa;
+ struct rsn_parms wpa2;
+ uint16 qbss_load_aac;
+
+ uint8 qbss_load_chan_free;
+ uint8 mcipher;
+ uint8 wpacfg;
+ uint16 mdid;
+ uint16 flags2;
+ uint32 vht_capabilities;
+ uint16 vht_rxmcsmap;
+ uint16 vht_txmcsmap;
+} wlc_bss_info_t;
+
+#define WLC_BSS_54G 0x0001
+#define WLC_BSS_RSSI_ON_CHANNEL 0x0002
+#define WLC_BSS_WME 0x0004
+#define WLC_BSS_BRCM 0x0008
+#define WLC_BSS_WPA 0x0010
+#define WLC_BSS_HT 0x0020
+#define WLC_BSS_40MHZ 0x0040
+#define WLC_BSS_WPA2 0x0080
+#define WLC_BSS_BEACON 0x0100
+#define WLC_BSS_40INTOL 0x0200
+#define WLC_BSS_SGI_20 0x0400
+#define WLC_BSS_SGI_40 0x0800
+#define WLC_BSS_CACHE 0x2000
+#define WLC_BSS_FBT 0x8000
+
+#define WLC_BSS_OVERDS_FBT 0x0001
+#define WLC_BSS_VHT 0x0002
+#define WLC_BSS_80MHZ 0x0004
+#define WLC_BSS_SGI_80 0x0008
+
+#define WLC_ENOIOCTL 1
+#define WLC_EINVAL 2
+#define WLC_ETOOSMALL 3
+#define WLC_ETOOBIG 4
+#define WLC_ERANGE 5
+#define WLC_EDOWN 6
+#define WLC_EUP 7
+#define WLC_ENOMEM 8
+#define WLC_EBUSY 9
+
+#define IOVF_BSSCFG_STA_ONLY (1<<0)
+#define IOVF_BSSCFG_AP_ONLY (1<<1)
+#define IOVF_BSS_SET_DOWN (1<<2)
+
+#define IOVF_MFG (1<<3)
+#define IOVF_WHL (1<<4)
+#define IOVF_NTRL (1<<5)
+
+#define IOVF_SET_UP (1<<6)
+#define IOVF_SET_DOWN (1<<7)
+#define IOVF_SET_CLK (1<<8)
+#define IOVF_SET_BAND (1<<9)
+
+#define IOVF_GET_UP (1<<10)
+#define IOVF_GET_DOWN (1<<11)
+#define IOVF_GET_CLK (1<<12)
+#define IOVF_GET_BAND (1<<13)
+#define IOVF_OPEN_ALLOW (1<<14)
+
+#define IOVF_BMAC_IOVAR (1<<15)
+
+#define BAR0_INVALID (1 << 0)
+#define VENDORID_INVALID (1 << 1)
+#define NOCARD_PRESENT (1 << 2)
+#define PHY_PLL_ERROR (1 << 3)
+#define DEADCHIP_ERROR (1 << 4)
+#define MACSPEND_TIMOUT (1 << 5)
+#define MACSPEND_WOWL_TIMOUT (1 << 6)
+#define DMATX_ERROR (1 << 7)
+#define DMARX_ERROR (1 << 8)
+#define DESCRIPTOR_ERROR (1 << 9)
+#define CARD_NOT_POWERED (1 << 10)
+
+#define WL_HEALTH_LOG(w, s) do {} while (0)
+
+typedef int (*watchdog_fn_t)(void *handle);
+typedef int (*up_fn_t)(void *handle);
+typedef int (*down_fn_t)(void *handle);
+typedef int (*dump_fn_t)(void *handle, struct bcmstrbuf *b);
+
+typedef int (*iovar_fn_t)(void *handle, const bcm_iovar_t *vi, uint32 actionid,
+ const char *name, void *params, uint plen, void *arg, int alen,
+ int vsize, struct wlc_if *wlcif);
+
+#define WLC_IOCF_BSSCFG_STA_ONLY (1<<0)
+#define WLC_IOCF_BSSCFG_AP_ONLY (1<<1)
+
+#define WLC_IOCF_MFG (1<<2)
+
+#define WLC_IOCF_DRIVER_UP (1<<3)
+#define WLC_IOCF_DRIVER_DOWN (1<<4)
+#define WLC_IOCF_CORE_CLK (1<<5)
+#define WLC_IOCF_FIXED_BAND (1<<6)
+#define WLC_IOCF_OPEN_ALLOW (1<<7)
+
+typedef int (*wlc_ioctl_fn_t)(void *handle, int cmd, void *arg, int len, struct wlc_if *wlcif);
+
+typedef struct wlc_ioctl_cmd_s {
+ uint16 cmd;
+ uint16 flags;
+ int min_len;
+} wlc_ioctl_cmd_t;
+
+typedef struct wlc_pub {
+ void *wlc;
+ struct ether_addr cur_etheraddr;
+ uint unit;
+ uint corerev;
+ osl_t *osh;
+ si_t *sih_obsolete;
+ char *vars_obsolete;
+ uint vars_size_obsolete;
+ bool up;
+ bool hw_off;
+ wlc_tunables_t *tunables;
+ bool hw_up;
+ bool _piomode;
+ uint _nbands;
+ uint now;
+
+ bool promisc;
+ bool delayed_down;
+ bool _ap;
+ bool _apsta;
+ bool _assoc_recreate;
+ int _wme;
+ uint8 _mbss;
+ bool associated;
+
+ bool phytest_on;
+ bool bf_preempt_4306;
+
+ bool _wowl;
+ bool _wowl_active;
+ bool _ampdu_tx;
+ bool _ampdu_rx;
+ bool _amsdu_tx;
+ bool _cac;
+ uint _spect_management;
+ uint8 _n_enab;
+ bool _n_reqd;
+
+ uint8 _vht_enab;
+
+ int8 _coex;
+ bool _priofc;
+ bool phy_bw40_capable;
+ bool phy_bw80_capable;
+
+ uint32 wlfeatureflag;
+ int psq_pkts_total;
+
+ uint16 txmaxpkts;
+
+ uint32 swdecrypt;
+
+ int bcmerror;
+
+ mbool radio_disabled;
+ mbool last_radio_disabled;
+ bool radio_active;
+ uint16 roam_time_thresh;
+ bool align_wd_tbtt;
+ uint16 boardrev;
+ uint8 sromrev;
+ uint32 boardflags;
+ uint32 boardflags2;
+
+ wl_cnt_t *_cnt;
+ wl_wme_cnt_t *_wme_cnt;
+
+ uint8 _ndis_cap;
+ bool _extsta;
+ bool _pkt_filter;
+ bool phy_11ncapable;
+ bool _fbt;
+ pktpool_t *pktpool;
+ uint8 _ampdumac;
+ bool _wleind;
+ bool _sup_enab;
+ uint driverrev;
+
+ bool _11h;
+ bool _11d;
+#ifdef WLCNTRY
+ bool _autocountry;
+#endif
+ uint32 health;
+ uint8 d11tpl_phy_hdr_len;
+ uint wsec_max_rcmta_keys;
+ uint max_addrma_idx;
+ uint16 m_seckindxalgo_blk;
+ uint m_seckindxalgo_blk_sz;
+ uint16 m_coremask_blk;
+ uint16 m_coremask_blk_wowl;
+#ifdef WL_BEAMFORMING
+ bool _txbf;
+#endif
+
+ bool wet_tunnel;
+ int _ol;
+
+ uint16 vht_features;
+
+ bool _ampdu_hostreorder;
+
+ int8 _pktc;
+ bool _tdls_support;
+ bool _okc;
+ bool _p2po;
+ bool _anqpo;
+ bool _wl_rxearlyrc;
+ bool _tiny_pktjoin;
+ si_t *sih;
+ char *vars;
+ uint vars_size;
+ bool _proxd;
+
+ bool _arpoe_support;
+ bool _11u;
+
+ bool _lpc_algo;
+ bool _relmcast;
+ bool _relmcast_support;
+
+ bool _l2_filter;
+
+ uint bcn_tmpl_len;
+#ifdef WL_OFFLOADSTATS
+ uint32 offld_cnt_received[4];
+ uint32 offld_cnt_consumed[4];
+#endif
+#ifdef WL_INTERRUPTSTATS
+ uint32 intr_cnt[32];
+#endif
+
+#ifdef TCPKAOE
+ bool _icmpoe;
+ bool _tcp_keepalive;
+#endif
+ bool _olpc;
+} wlc_pub_t;
+
+typedef struct wl_rxsts {
+ uint pkterror;
+ uint phytype;
+ chanspec_t chanspec;
+ uint16 datarate;
+ uint8 mcs;
+ uint8 htflags;
+ uint antenna;
+ uint pktlength;
+ uint32 mactime;
+ uint sq;
+ int32 signal;
+ int32 noise;
+ uint preamble;
+ uint encoding;
+ uint nfrmtype;
+ struct wl_if *wlif;
+ uint8 nss;
+ uint8 coding;
+ uint16 aid;
+ uint8 gid;
+ uint8 bw;
+ uint16 vhtflags;
+ uint8 bw_nonht;
+ uint32 ampdu_counter;
+} wl_rxsts_t;
+
+typedef struct wl_txsts {
+ uint pkterror;
+ uint phytype;
+ chanspec_t chanspec;
+ uint16 datarate;
+ uint8 mcs;
+ uint8 htflags;
+ uint antenna;
+ uint pktlength;
+ uint32 mactime;
+ uint preamble;
+ uint encoding;
+ uint nfrmtype;
+ uint txflags;
+ uint retries;
+ struct wl_if *wlif;
+} wl_txsts_t;
+
+typedef struct wlc_if_stats {
+
+ uint32 txframe;
+ uint32 txbyte;
+ uint32 txerror;
+ uint32 txnobuf;
+ uint32 txrunt;
+ uint32 txfail;
+
+ uint32 rxframe;
+ uint32 rxbyte;
+ uint32 rxerror;
+ uint32 rxnobuf;
+ uint32 rxrunt;
+ uint32 rxfragerr;
+
+ uint32 txretry;
+ uint32 txretrie;
+ uint32 txfrmsnt;
+ uint32 txmulti;
+ uint32 txfrag;
+
+ uint32 rxmulti;
+
+} wlc_if_stats_t;
+
+#define WL_RXS_CRC_ERROR 0x00000001
+#define WL_RXS_RUNT_ERROR 0x00000002
+#define WL_RXS_ALIGN_ERROR 0x00000004
+#define WL_RXS_OVERSIZE_ERROR 0x00000008
+#define WL_RXS_WEP_ICV_ERROR 0x00000010
+#define WL_RXS_WEP_ENCRYPTED 0x00000020
+#define WL_RXS_PLCP_SHORT 0x00000040
+#define WL_RXS_DECRYPT_ERR 0x00000080
+#define WL_RXS_OTHER_ERR 0x80000000
+
+#define WL_RXS_PHY_A 0x00000000
+#define WL_RXS_PHY_B 0x00000001
+#define WL_RXS_PHY_G 0x00000002
+#define WL_RXS_PHY_N 0x00000004
+
+#define WL_RXS_ENCODING_UNKNOWN 0x00000000
+#define WL_RXS_ENCODING_DSSS_CCK 0x00000001
+#define WL_RXS_ENCODING_OFDM 0x00000002
+#define WL_RXS_ENCODING_HT 0x00000003
+#define WL_RXS_ENCODING_VHT 0x00000004
+
+#define WL_RXS_UNUSED_STUB 0x0
+#define WL_RXS_PREAMBLE_SHORT 0x00000001
+#define WL_RXS_PREAMBLE_LONG 0x00000002
+#define WL_RXS_PREAMBLE_HT_MM 0x00000003
+#define WL_RXS_PREAMBLE_HT_GF 0x00000004
+
+#define WL_RXS_HTF_BW_MASK 0x07
+#define WL_RXS_HTF_40 0x01
+#define WL_RXS_HTF_20L 0x02
+#define WL_RXS_HTF_20U 0x04
+#define WL_RXS_HTF_SGI 0x08
+#define WL_RXS_HTF_STBC_MASK 0x30
+#define WL_RXS_HTF_STBC_SHIFT 4
+#define WL_RXS_HTF_LDPC 0x40
+
+#define WL_RXS_VHTF_STBC 0x01
+#define WL_RXS_VHTF_TXOP_PS 0x02
+#define WL_RXS_VHTF_SGI 0x04
+#define WL_RXS_VHTF_SGI_NSYM_DA 0x08
+#define WL_RXS_VHTF_LDPC_EXTRA 0x10
+#define WL_RXS_VHTF_BF 0x20
+#define WL_RXS_VHTF_DYN_BW_NONHT 0x40
+
+#define WL_RXS_VHTF_CODING_LDCP 0x01
+
+#define WL_RXS_VHT_BW_20 0
+#define WL_RXS_VHT_BW_40 1
+#define WL_RXS_VHT_BW_20L 2
+#define WL_RXS_VHT_BW_20U 3
+#define WL_RXS_VHT_BW_80 4
+#define WL_RXS_VHT_BW_40L 5
+#define WL_RXS_VHT_BW_40U 6
+#define WL_RXS_VHT_BW_20LL 7
+#define WL_RXS_VHT_BW_20LU 8
+#define WL_RXS_VHT_BW_20UL 9
+#define WL_RXS_VHT_BW_20UU 10
+
+#define WL_RXS_NFRM_AMPDU_FIRST 0x00000001
+#define WL_RXS_NFRM_AMPDU_SUB 0x00000002
+#define WL_RXS_NFRM_AMSDU_FIRST 0x00000004
+#define WL_RXS_NFRM_AMSDU_SUB 0x00000008
+#define WL_RXS_NFRM_AMPDU_NONE 0x00000100
+
+#define WL_TXS_TXF_FAIL 0x01
+#define WL_TXS_TXF_CTS 0x02
+#define WL_TXS_TXF_RTSCTS 0x04
+
+#define BPRESET_ENAB(pub) (0)
+
+#define AP_ENAB(pub) (0)
+
+#define APSTA_ENAB(pub) (0)
+
+#define PSTA_ENAB(pub) (0)
+
+#if defined(PKTC_DONGLE)
+#define PKTC_ENAB(pub) ((pub)->_pktc)
+#else
+#define PKTC_ENAB(pub) (0)
+#endif
+
+#if defined(WL_BEAMFORMING)
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define TXBF_ENAB(pub) ((pub)->_txbf)
+ #elif defined(WLTXBF_DISABLED)
+ #define TXBF_ENAB(pub) (0)
+ #else
+ #define TXBF_ENAB(pub) (1)
+ #endif
+#else
+ #define TXBF_ENAB(pub) (0)
+#endif
+
+#define STA_ONLY(pub) (!AP_ENAB(pub))
+#define AP_ONLY(pub) (AP_ENAB(pub) && !APSTA_ENAB(pub))
+
+ #define PROP_TXSTATUS_ENAB(pub) 0
+
+#define WLOFFLD_CAP(wlc) ((wlc)->ol != NULL)
+#define WLOFFLD_ENAB(pub) ((pub)->_ol)
+#define WLOFFLD_BCN_ENAB(pub) ((pub)->_ol & OL_BCN_ENAB)
+#define WLOFFLD_ARP_ENAB(pub) ((pub)->_ol & OL_ARP_ENAB)
+#define WLOFFLD_ND_ENAB(pub) ((pub)->_ol & OL_ND_ENAB)
+#define WLOFFLD_ARM_TX(pub) ((pub)->_ol & OL_ARM_TX_ENAB)
+
+#define WOWL_ENAB(pub) ((pub)->_wowl)
+#define WOWL_ACTIVE(pub) ((pub)->_wowl_active)
+
+ #define DPT_ENAB(pub) 0
+
+ #define TDLS_SUPPORT(pub) (0)
+ #define TDLS_ENAB(pub) (0)
+
+#define WLDLS_ENAB(pub) 0
+
+#ifdef WL_OKC
+ #if defined(WL_ENAB_RUNTIME_CHECK)
+#define OKC_ENAB(pub) ((pub)->_okc)
+ #elif defined(WL_OKC_DISABLED)
+ #define OKC_ENAB(pub) (0)
+#else
+ #define OKC_ENAB(pub) ((pub)->_okc)
+#endif
+#else
+ #define OKC_ENAB(pub) (0)
+#endif
+
+#define WLBSSLOAD_ENAB(pub) (0)
+
+ #define MCNX_ENAB(pub) 0
+
+ #define P2P_ENAB(pub) 0
+
+ #define MCHAN_ENAB(pub) (0)
+ #define MCHAN_ACTIVE(pub) (0)
+
+ #define MQUEUE_ENAB(pub) (0)
+
+ #define BTA_ENAB(pub) (0)
+
+#define PIO_ENAB(pub) 0
+
+#define CAC_ENAB(pub) ((pub)->_cac)
+
+#define COEX_ACTIVE(wlc) 0
+#define COEX_ENAB(pub) 0
+
+#define RXIQEST_ENAB(pub) (0)
+
+#define EDCF_ENAB(pub) (WME_ENAB(pub))
+#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
+
+#define PRIOFC_ENAB(pub) ((pub)->_priofc)
+
+#define MONITOR_ENAB(wlc) ((wlc)->monitor != 0)
+
+#define PROMISC_ENAB(wlc_pub) (wlc_pub)->promisc
+
+#define WLC_SENDUP_MGMT_ENAB(cfg) 0
+
+ #define TOE_ENAB(pub) (0)
+
+ #define ARPOE_SUPPORT(pub) (0)
+ #define ARPOE_ENAB(pub) (0)
+#define ICMPOE_ENAB(pub) 0
+
+ #define NWOE_ENAB(pub) (0)
+
+#define TRAFFIC_MGMT_ENAB(pub) 0
+
+ #define L2_FILTER_ENAB(pub) (0)
+
+#define NET_DETECT_ENAB(pub) 0
+
+#ifdef PACKET_FILTER
+#define PKT_FILTER_ENAB(pub) ((pub)->_pkt_filter)
+#else
+#define PKT_FILTER_ENAB(pub) 0
+#endif
+
+#ifdef P2PO
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define P2PO_ENAB(pub) ((pub)->_p2po)
+ #elif defined(P2PO_DISABLED)
+ #define P2PO_ENAB(pub) (0)
+ #else
+ #define P2PO_ENAB(pub) (1)
+ #endif
+#else
+ #define P2PO_ENAB(pub) 0
+#endif
+
+#ifdef ANQPO
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define ANQPO_ENAB(pub) ((pub)->_anqpo)
+ #elif defined(ANQPO_DISABLED)
+ #define ANQPO_ENAB(pub) (0)
+ #else
+ #define ANQPO_ENAB(pub) (1)
+ #endif
+#else
+ #define ANQPO_ENAB(pub) 0
+#endif
+
+#define ASSOC_RECREATE_ENAB(pub) 0
+
+#define WLFBT_ENAB(pub) (0)
+
+#if 0 && (NDISVER >= 0x0620)
+#define WIN7_AND_UP_OS(pub) ((pub)->_ndis_cap)
+#else
+#define WIN7_AND_UP_OS(pub) 0
+#endif
+
+ #define NDOE_ENAB(pub) (0)
+
+ #define WLEXTSTA_ENAB(pub) 0
+
+ #define IBSS_PEER_GROUP_KEY_ENAB(pub) (0)
+
+ #define IBSS_PEER_DISCOVERY_EVENT_ENAB(pub) (0)
+
+ #define IBSS_PEER_MGMT_ENAB(pub) (0)
+
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define WLEIND_ENAB(pub) ((pub)->_wleind)
+ #elif defined(WLEIND_DISABLED)
+ #define WLEIND_ENAB(pub) (0)
+ #else
+ #define WLEIND_ENAB(pub) (1)
+ #endif
+
+ #define CCX_ENAB(pub) 0
+
+ #define BCMAUTH_PSK_ENAB(pub) 0
+
+ #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+ #define SUP_ENAB(pub) ((pub)->_sup_enab)
+ #elif defined(BCMSUP_PSK_DISABLED)
+ #define SUP_ENAB(pub) (0)
+ #else
+ #define SUP_ENAB(pub) (1)
+ #endif
+
+#define WLC_PREC_BMP_ALL MAXBITVAL(WLC_PREC_COUNT)
+
+#define WLC_PREC_BMP_AC_BE (NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BE)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \
+ NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_EE)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
+#define WLC_PREC_BMP_AC_BK (NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BK)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \
+ NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NONE)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
+#define WLC_PREC_BMP_AC_VI (NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_CL)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \
+ NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VI)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
+#define WLC_PREC_BMP_AC_VO (NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VO)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \
+ NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NC)) | \
+ NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
+
+#define WME_ENAB(pub) ((pub)->_wme != OFF)
+#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
+
+#ifdef WLCNTRY
+#define WLC_AUTOCOUNTRY_ENAB(wlc) ((wlc)->pub->_autocountry)
+#else
+#define WLC_AUTOCOUNTRY_ENAB(wlc) FALSE
+#endif
+
+#define WL11D_ENAB(wlc) ((wlc)->pub->_11d)
+
+#define WL11H_ENAB(wlc) ((wlc)->pub->_11h)
+
+#define WL11U_ENAB(wlc) FALSE
+
+#define WLPROBRESP_SW_ENAB(wlc) FALSE
+
+#define LPC_ENAB(wlc) (FALSE)
+
+#if defined(WLOLPC)
+#define OLPC_ENAB(wlc) ((wlc)->pub->_olpc)
+#else
+#define OLPC_ENAB(wlc) (FALSE)
+#endif
+
+#ifdef WL_RELMCAST
+ #if defined(WL_ENAB_RUNTIME_CHECK)
+ #define RMC_SUPPORT(pub) ((pub)->_relmcast_support)
+ #define RMC_ENAB(pub) ((pub)->_relmcast)
+ #elif defined(WL_RELMCAST_DISABLED)
+ #define RMC_SUPPORT(pub) (0)
+ #define RMC_ENAB(pub) (0)
+ #else
+ #define RMC_SUPPORT(pub) (1)
+ #define RMC_ENAB(pub) ((pub)->_relmcast)
+ #endif
+#else
+ #define RMC_SUPPORT(pub) (0)
+ #define RMC_ENAB(pub) (0)
+#endif
+
+#define WLC_USE_COREFLAGS 0xffffffff
+
+#define WLC_UPDATE_STATS(wlc) 1
+#define WLCNTINCR(a) ((a)++)
+#define WLCNTCONDINCR(c, a) do { if (c) (a)++; } while (0)
+#define WLCNTDECR(a) ((a)--)
+#define WLCNTADD(a,delta) ((a) += (delta))
+#define WLCNTSET(a,value) ((a) = (value))
+#define WLCNTVAL(a) (a)
+
+#if !defined(RXCHAIN_PWRSAVE) && !defined(RADIO_PWRSAVE)
+#define WLPWRSAVERXFADD(wlc, v)
+#define WLPWRSAVERXFINCR(wlc)
+#define WLPWRSAVETXFINCR(wlc)
+#define WLPWRSAVERXFVAL(wlc) 0
+#define WLPWRSAVETXFVAL(wlc) 0
+#endif
+
+struct wlc_dpc_info {
+ uint processed;
+};
+
+extern void *wlc_attach(void *wl, uint16 vendor, uint16 device, uint unit, bool piomode,
+ osl_t *osh, void *regsva, uint bustype, void *btparam, uint *perr);
+extern uint wlc_detach(struct wlc_info *wlc);
+extern int wlc_up(struct wlc_info *wlc);
+extern uint wlc_down(struct wlc_info *wlc);
+
+extern int wlc_set(struct wlc_info *wlc, int cmd, int arg);
+extern int wlc_get(struct wlc_info *wlc, int cmd, int *arg);
+extern int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg);
+extern int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg);
+extern bool wlc_chipmatch(uint16 vendor, uint16 device);
+extern void wlc_init(struct wlc_info *wlc);
+extern void wlc_reset(struct wlc_info *wlc);
+#ifdef MCAST_REGEN
+extern int32 wlc_mcast_reverse_translation(struct ether_header *eh);
+#endif
+
+extern void wlc_intrson(struct wlc_info *wlc);
+extern uint32 wlc_intrsoff(struct wlc_info *wlc);
+extern void wlc_intrsrestore(struct wlc_info *wlc, uint32 macintmask);
+extern bool wlc_intrsupd(struct wlc_info *wlc);
+extern bool wlc_isr(struct wlc_info *wlc, bool *wantdpc);
+extern bool wlc_dpc(struct wlc_info *wlc, bool bounded, struct wlc_dpc_info *dpc);
+
+extern bool wlc_sendpkt(struct wlc_info *wlc, void *sdu, struct wlc_if *wlcif);
+extern bool wlc_send80211_specified(wlc_info_t *wlc, void *sdu, uint32 rspec, struct wlc_if *wlcif);
+extern bool wlc_send80211_raw(struct wlc_info *wlc, wlc_if_t *wlcif, void *p, uint ac);
+extern int wlc_iovar_op(struct wlc_info *wlc, const char *name, void *params, int p_len, void *arg,
+ int len, bool set, struct wlc_if *wlcif);
+extern int wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len, struct wlc_if *wlcif);
+
+extern void wlc_statsupd(struct wlc_info *wlc);
+
+extern wlc_pub_t *wlc_pub(void *wlc);
+
+extern void tcm_sem_enter(wlc_info_t *wlc);
+extern void tcm_sem_exit(wlc_info_t *wlc);
+extern void tcm_sem_cleanup(wlc_info_t *wlc);
+
+extern int wlc_module_register(wlc_pub_t *pub, const bcm_iovar_t *iovars,
+ const char *name, void *hdl, iovar_fn_t iovar_fn,
+ watchdog_fn_t watchdog_fn, up_fn_t up_fn, down_fn_t down_fn);
+extern int wlc_module_unregister(wlc_pub_t *pub, const char *name, void *hdl);
+extern int wlc_module_add_ioctl_fn(wlc_pub_t *pub, void *hdl,
+ wlc_ioctl_fn_t ioctl_fn,
+ int num_cmds, const wlc_ioctl_cmd_t *ioctls);
+extern int wlc_module_remove_ioctl_fn(wlc_pub_t *pub, void *hdl);
+
+#define WLC_RPCTX_PARAMS 32
+
+extern void wlc_wlcif_stats_get(wlc_info_t *wlc, wlc_if_t *wlcif, wlc_if_stats_t *wlcif_stats);
+extern wlc_if_t *wlc_wlcif_get_by_index(wlc_info_t *wlc, uint idx);
+
+#if defined(BCMDBG)
+
+#define WLC_PERF_STATS_ISR 0x01
+#define WLC_PERF_STATS_DPC 0x02
+#define WLC_PERF_STATS_TMR_DPC 0x04
+#define WLC_PERF_STATS_PRB_REQ 0x08
+#define WLC_PERF_STATS_PRB_RESP 0x10
+#define WLC_PERF_STATS_BCN_ISR 0x20
+#define WLC_PERF_STATS_BCNS 0x40
+
+void wlc_update_perf_stats(wlc_info_t *wlc, uint32 mask);
+void wlc_update_isr_stats(wlc_info_t *wlc, uint32 macintstatus);
+#endif
+
+#define WLC_REPLAY_CNTRS_VALUE WPA_CAP_4_REPLAY_CNTRS
+
+#if WLC_REPLAY_CNTRS_VALUE == WPA_CAP_16_REPLAY_CNTRS
+#define PRIO2IVIDX(prio) (prio)
+#elif WLC_REPLAY_CNTRS_VALUE == WPA_CAP_4_REPLAY_CNTRS
+#define PRIO2IVIDX(prio) WME_PRIO2AC(prio)
+#else
+#error "Neither WPA_CAP_4_REPLAY_CNTRS nor WPA_CAP_16_REPLAY_CNTRS is used"
+#endif
+
+#define GPIO_2_PA_CTRL_5G_0 0x4
+
+#ifdef WL_INTERRUPTSTATS
+typedef enum {
+ nMI_MACSSPNDD = 0,
+ nMI_BCNTPL,
+ nMI_TBTT,
+ nMI_BCNSUCCESS,
+ nMI_BCNCANCLD,
+ nMI_ATIMWINEND,
+ nMI_PMQ,
+ nMI_NSPECGEN_0,
+ nMI_NSPECGEN_1,
+ nMI_MACTXERR,
+ nMI_NSPECGEN_3,
+ nMI_PHYTXERR,
+ nMI_PME,
+ nMI_GP0,
+ nMI_GP1,
+ nMI_DMAINT,
+ nMI_TXSTOP,
+ nMI_CCA,
+ nMI_BG_NOISE,
+ nMI_DTIM_TBTT,
+ nMI_PRQ,
+ nMI_PWRUP,
+ nMI_BT_RFACT_STUCK,
+ nMI_BT_PRED_REQ,
+ nMI_NOTUSED,
+ nMI_P2P,
+ nMI_DMATX,
+ nMI_TSSI_LIMIT,
+ nMI_RFDISABLE,
+ nMI_TFS,
+ nMI_PHYCHANGED,
+ nMI_TO
+} intr_enum;
+
+#define WLCINC_INTRCNT(intr) (wlc->pub->intr_cnt[(intr)]++)
+#else
+#define WLCINC_INTRCNT(intr)
+#endif
+
+#if defined(CONFIG_WL) || defined(CONFIG_WL_MODULE)
+#define WL_RTR() TRUE
+#else
+#define WL_RTR() FALSE
+#endif
+
+#endif
diff --git a/src/wl/sys/wlc_types.h b/src/wl/sys/wlc_types.h
new file mode 100644
index 0000000..42fcb37
--- /dev/null
+++ b/src/wl/sys/wlc_types.h
@@ -0,0 +1,137 @@
+/*
+ * Forward declarations for commonly used wl driver structs
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_types.h 402685 2013-05-16 17:47:20Z $
+ */
+
+#ifndef _wlc_types_h_
+#define _wlc_types_h_
+
+typedef struct wlc_info wlc_info_t;
+typedef struct wlc_bsscfg wlc_bsscfg_t;
+typedef struct vndr_ie_listel vndr_ie_listel_t;
+typedef struct wlc_if wlc_if_t;
+typedef struct wl_if wl_if_t;
+typedef struct led_info led_info_t;
+typedef struct bmac_led bmac_led_t;
+typedef struct bmac_led_info bmac_led_info_t;
+typedef struct seq_cmds_info wlc_seq_cmds_info_t;
+typedef struct wlc_ccx ccx_t;
+typedef struct wlc_ccx_rm ccx_rm_t;
+typedef struct apps_wlc_psinfo apps_wlc_psinfo_t;
+typedef struct scb_module scb_module_t;
+typedef struct ba_info ba_info_t;
+typedef struct wlc_frminfo wlc_frminfo_t;
+typedef struct amsdu_info amsdu_info_t;
+typedef struct cram_info cram_info_t;
+typedef struct wlc_extlog_info wlc_extlog_info_t;
+typedef struct wlc_txq_info wlc_txq_info_t;
+typedef struct wlc_hrt_info wlc_hrt_info_t;
+typedef struct wlc_hrt_to wlc_hrt_to_t;
+typedef struct wlc_cac wlc_cac_t;
+typedef struct ampdu_tx_info ampdu_tx_info_t;
+typedef struct ampdu_rx_info ampdu_rx_info_t;
+typedef struct wlc_ratesel_info wlc_ratesel_info_t;
+typedef struct ratesel_info ratesel_info_t;
+typedef struct wlc_ap_info wlc_ap_info_t;
+typedef struct wlc_scan_info wlc_scan_info_t;
+typedef struct dpt_info dpt_info_t;
+typedef struct tdls_info tdls_info_t;
+typedef struct dls_info dls_info_t;
+typedef struct l2_filter_info l2_filter_info_t;
+typedef struct wlc_auth_info wlc_auth_info_t;
+typedef struct wlc_psta_info wlc_psta_info_t;
+typedef struct wlc_psa wlc_psa_t;
+typedef struct wowl_info wowl_info_t;
+typedef struct wlc_plt_info wlc_plt_pub_t;
+typedef struct supplicant supplicant_t;
+typedef struct authenticator authenticator_t;
+typedef struct antsel_info antsel_info_t;
+typedef struct bmac_pmq bmac_pmq_t;
+typedef struct wlc_rrm_info wlc_rrm_info_t;
+typedef struct rm_info rm_info_t;
+
+struct d11init;
+
+#ifndef _hnddma_pub_
+#define _hnddma_pub_
+typedef const struct hnddma_pub hnddma_t;
+#endif
+
+typedef struct wlc_dpc_info wlc_dpc_info_t;
+
+typedef struct wlc_11h_info wlc_11h_info_t;
+typedef struct wlc_tpc_info wlc_tpc_info_t;
+typedef struct wlc_csa_info wlc_csa_info_t;
+typedef struct wlc_quiet_info wlc_quiet_info_t;
+typedef struct cca_info cca_info_t;
+typedef struct itfr_info itfr_info_t;
+
+typedef struct wlc_ol_info_t wlc_ol_info_t;
+#ifdef WLOLPC
+typedef struct wlc_olpc_eng_info_t wlc_olpc_eng_info_t;
+#endif
+typedef void(*wlc_stf_txchain_evt_notify)(wlc_info_t *wlc);
+
+typedef struct wlc_11d_info wlc_11d_info_t;
+typedef struct wlc_cntry_info wlc_cntry_info_t;
+
+typedef struct wlc_dfs_info wlc_dfs_info_t;
+
+typedef struct bsscfg_module bsscfg_module_t;
+
+typedef struct wlc_prq_info_s wlc_prq_info_t;
+
+typedef struct wlc_prot_info wlc_prot_info_t;
+typedef struct wlc_prot_g_info wlc_prot_g_info_t;
+typedef struct wlc_prot_n_info wlc_prot_n_info_t;
+
+typedef struct wlc_11u_info wlc_11u_info_t;
+typedef struct wlc_probresp_info wlc_probresp_info_t;
+typedef struct wlc_wapi_info wlc_wapi_info_t;
+
+typedef struct wlc_bssload_info wlc_bssload_info_t;
+
+typedef struct wlc_rfc wlc_rfc_t;
+typedef struct wlc_pktc_info wlc_pktc_info_t;
+
+typedef struct wlc_lpc_info wlc_lpc_info_t;
+typedef struct lpc_info lpc_info_t;
+typedef struct rate_lcb_info rate_lcb_info_t;
+
+typedef struct wlc_txbf_info wlc_txbf_info_t;
+
+typedef struct wlc_bcn_clsg_info wlc_bcn_clsg_info_t;
+
+typedef struct wlc_nar_info wlc_nar_info_t;
+
+typedef struct wlc_relmcast_info wlc_relmcast_info_t;
+
+typedef struct okc_info okc_info_t;
+
+typedef struct wlc_gas_info wlc_gas_info_t;
+typedef struct wlc_p2po_info wlc_p2po_info_t;
+typedef struct wlc_disc_info wlc_disc_info_t;
+typedef struct wlc_anqpo_info wlc_anqpo_info_t;
+
+typedef struct wlc_pdsvc_info wlc_pdsvc_info_t;
+
+typedef struct wlc_hw wlc_hw_t;
+typedef struct wlc_hw_info wlc_hw_info_t;
+typedef struct wlc_hwband wlc_hwband_t;
+
+#endif
diff --git a/src/wl/sys/wlc_utils.h b/src/wl/sys/wlc_utils.h
new file mode 100644
index 0000000..194ca69
--- /dev/null
+++ b/src/wl/sys/wlc_utils.h
@@ -0,0 +1,51 @@
+/*
+ * utilities related header file
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_p2p.h 274724 2011-08-01 17:06:47Z $
+ */
+
+#ifndef _wlc_utils_h_
+#define _wlc_utils_h_
+
+#include <typedefs.h>
+
+struct rsn_parms {
+ uint8 flags;
+ uint8 multicast;
+ uint8 ucount;
+ uint8 unicast[4];
+ uint8 acount;
+ uint8 auth[4];
+ uint8 PAD[4];
+ uint8 cap[4];
+};
+
+typedef struct rsn_parms rsn_parms_t;
+
+extern void wlc_uint64_add(uint32* high, uint32* low, uint32 inc_high, uint32 inc_low);
+extern void wlc_uint64_sub(uint32* a_high, uint32* a_low, uint32 b_high, uint32 b_low);
+extern bool wlc_uint64_lt(uint32 a_high, uint32 a_low, uint32 b_high, uint32 b_low);
+extern uint32 wlc_calc_tbtt_offset(uint32 bi, uint32 tsf_h, uint32 tsf_l);
+extern uint32 wlc_calc_next_pos32(uint32 tsf, uint32 cur, uint32 interval, bool wrap);
+extern void wlc_tsf64_to_next_tbtt64(uint32 bcn_int, uint32 *tsf_h, uint32 *tsf_l);
+extern void wlc_tbtt21_to_tbtt32(uint32 tsf_l, uint32 *tbtt_l);
+extern void wlc_tbtt21_to_tbtt64(uint32 tsf_h, uint32 tsf_l, uint32 *tbtt_h, uint32 *tbtt_l);
+
+extern bool wlc_rsn_ucast_lookup(struct rsn_parms *rsn, uint8 auth);
+extern bool wlc_rsn_akm_lookup(struct rsn_parms *rsn, uint8 akm);
+
+#endif
diff --git a/src/wl/sys/wlc_wowl.h b/src/wl/sys/wlc_wowl.h
new file mode 100644
index 0000000..d21eb58
--- /dev/null
+++ b/src/wl/sys/wlc_wowl.h
@@ -0,0 +1,86 @@
+/*
+ * Wake-on-Wireless related header file
+ *
+ * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: wlc_wowl.h 458427 2014-02-26 23:12:38Z $
+*/
+
+#ifndef _wlc_wowl_h_
+#define _wlc_wowl_h_
+
+#define WLC_WOWL_OFFLOADS
+
+extern wowl_info_t *wlc_wowl_attach(wlc_info_t *wlc);
+extern void wlc_wowl_detach(wowl_info_t *wowl);
+extern bool wlc_wowl_cap(struct wlc_info *wlc);
+extern bool wlc_wowl_enable(wowl_info_t *wowl);
+extern uint32 wlc_wowl_clear(wowl_info_t *wowl);
+void wlc_wowl_wake_reason_process(wlc_info_t *wlc);
+#if defined(WLC_WOWL_OFFLOADS)
+extern void wlc_wowl_set_wpa_m1(wowl_info_t *wowl);
+extern void wlc_wowl_set_eapol_id(wowl_info_t *wowl);
+extern int wlc_wowl_set_key_info(wowl_info_t *wowl, uint32 offload_id, void *kek,
+ int kek_len, void* kck, int kck_len, void *replay_counter, int replay_counter_len);
+extern int wlc_wowl_add_offload_ipv4_arp(wowl_info_t *wowl, uint32 offload_id,
+ uint8 * RemoteIPv4Address, uint8 *HostIPv4Address, uint8 * MacAddress);
+extern int wlc_wowl_add_offload_ipv6_ns(wowl_info_t *wowl, uint32 offload_id,
+ uint8 * RemoteIPv6Address, uint8 *SolicitedNodeIPv6Address,
+ uint8 * MacAddress, uint8 * TargetIPv6Address1, uint8 * TargetIPv6Address2);
+
+extern void wlc_wowl_set_keepalive(wowl_info_t *wowl, uint16 period_keepalive);
+extern uint8 *wlc_wowl_solicitipv6_addr(uint8 *TargetIPv6Address1, uint8 *solicitaddress);
+extern int wlc_wowl_remove_offload(wowl_info_t *wowl, uint32 offload_id, uint32 * type);
+extern int wlc_wowl_get_replay_counter(wowl_info_t *wowl, void *replay_counter, int *len);
+
+extern void wlc_wowl_enable_completed(wowl_info_t *wowl);
+extern void wlc_wowl_disable_completed(wowl_info_t *wowl, void *wowl_host_info);
+#endif
+
+#define WOWL_IPV4_ARP_TYPE 0
+#define WOWL_IPV6_NS_TYPE 1
+#define WOWL_DOT11_RSN_REKEY_TYPE 2
+#define WOWL_OFFLOAD_INVALID_TYPE 3
+
+#define WOWL_IPV4_ARP_IDX 0
+#define WOWL_IPV6_NS_0_IDX 1
+#define WOWL_IPV6_NS_1_IDX 2
+#define WOWL_DOT11_RSN_REKEY_IDX 3
+#define WOWL_OFFLOAD_INVALID_IDX 4
+
+#define MAX_WOWL_OFFLOAD_ROWS 4
+#define MAX_WOWL_IPV6_ARP_PATTERNS 1
+#define MAX_WOWL_IPV6_NS_PATTERNS 2
+#define MAX_WOWL_IPV6_NS_OFFLOADS 1
+
+#define WOWL_INT_RESERVED_MASK 0xFF000000
+#define WOWL_INT_DATA_MASK 0x00FFFFFF
+#define WOWL_INT_PATTERN_FLAG 0x80000000
+#define WOWL_INT_NS_TA2_FLAG 0x40000000
+#define WOWL_INT_PATTERN_IDX_MASK 0x0F000000
+#define WOWL_INT_PATTERN_IDX_SHIFT 24
+
+#define MAXPATTERNS(wlc) \
+ (wlc_wowl_cap(wlc) ? \
+ (WLOFFLD_CAP(wlc) ? 12 : \
+ ((D11REV_GE((wlc)->pub->corerev, 15) && D11REV_LT((wlc)->pub->corerev, 40)) ? 12 : 4)) \
+ : 0)
+
+#define WOWL_OFFLOAD_ENABLED(wlc) \
+ ((CHIPID(wlc->pub->sih->chip) == BCM4360_CHIP_ID) || WIN7_AND_UP_OS(wlc->pub))
+
+#define WOWL_KEEPALIVE_FIXED_PARAM 11
+
+#endif